mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #118120 - compiler-errors:closure-kind, r=lcnr
Remove `PredicateKind::ClosureKind` We don't need the `ClosureKind` predicate kind -- instead, `Fn`-family trait goals are left as ambiguous, and we only need to make progress on `FnOnce` projection goals for inference purposes. This is similar to how we do confirmation of `Fn`-family trait and projection goals in the new trait solver, which also doesn't use the `ClosureKind` predicate. Some hacky logic is added in the second commit so that we can keep the error messages the same.
This commit is contained in:
commit
1e9dda77b5
@ -662,7 +662,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// this closure yet; this is exactly why the other
|
||||
// code is looking for a self type of an unresolved
|
||||
// inference variable.
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
=> None,
|
||||
},
|
||||
|
@ -906,12 +906,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
|
||||
}
|
||||
|
||||
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
|
||||
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
|
||||
where
|
||||
T: at::ToTrace<'tcx>,
|
||||
{
|
||||
let origin = &ObligationCause::dummy();
|
||||
self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok())
|
||||
self.probe(|_| {
|
||||
self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
|
||||
|
@ -308,9 +308,6 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
|
||||
// Nothing to elaborate in a projection predicate.
|
||||
}
|
||||
ty::PredicateKind::ClosureKind(..) => {
|
||||
// Nothing to elaborate when waiting for a closure's kind to be inferred.
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
|
||||
// Currently, we do not elaborate const-evaluatable
|
||||
// predicates.
|
||||
|
@ -263,9 +263,6 @@ impl FlagComputation {
|
||||
self.add_args(slice::from_ref(&arg));
|
||||
}
|
||||
ty::PredicateKind::ObjectSafe(_def_id) => {}
|
||||
ty::PredicateKind::ClosureKind(_def_id, args, _kind) => {
|
||||
self.add_args(args);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
|
||||
self.add_const(uv);
|
||||
}
|
||||
|
@ -548,7 +548,6 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||
| PredicateKind::AliasRelate(..)
|
||||
| PredicateKind::ObjectSafe(_)
|
||||
| PredicateKind::ClosureKind(_, _, _)
|
||||
| PredicateKind::Subtype(_)
|
||||
| PredicateKind::Coerce(_)
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
|
||||
@ -1276,7 +1275,6 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::WellFormed(..))
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
|
||||
| PredicateKind::ConstEquate(..)
|
||||
@ -1296,7 +1294,6 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::WellFormed(..))
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
|
||||
| PredicateKind::ConstEquate(..)
|
||||
@ -1317,7 +1314,6 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::WellFormed(..))
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous => None,
|
||||
|
@ -2781,11 +2781,6 @@ define_print! {
|
||||
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
||||
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
|
||||
}
|
||||
ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!(
|
||||
"the closure `",
|
||||
print_value_path(closure_def_id, &[]),
|
||||
write("` implements the trait `{}`", kind)
|
||||
),
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
||||
}
|
||||
|
@ -1809,13 +1809,6 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
|
||||
PredicateKind::ObjectSafe(did) => {
|
||||
stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did))
|
||||
}
|
||||
PredicateKind::ClosureKind(did, generic_args, closure_kind) => {
|
||||
stable_mir::ty::PredicateKind::ClosureKind(
|
||||
tables.closure_def(*did),
|
||||
generic_args.stable(tables),
|
||||
closure_kind.stable(tables),
|
||||
)
|
||||
}
|
||||
PredicateKind::Subtype(subtype_predicate) => {
|
||||
stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables))
|
||||
}
|
||||
|
@ -406,8 +406,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
ty::PredicateKind::Coerce(predicate) => {
|
||||
self.compute_coerce_goal(Goal { param_env, predicate })
|
||||
}
|
||||
ty::PredicateKind::ClosureKind(def_id, args, kind) => self
|
||||
.compute_closure_kind_goal(Goal { param_env, predicate: (def_id, args, kind) }),
|
||||
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
||||
self.compute_object_safe_goal(trait_def_id)
|
||||
}
|
||||
|
@ -135,7 +135,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||
}
|
||||
ty::PredicateKind::Clause(_)
|
||||
| ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(_, _, _)
|
||||
| ty::PredicateKind::Ambiguous => {
|
||||
FulfillmentErrorCode::CodeSelectionError(
|
||||
SelectionError::Unimplemented,
|
||||
|
@ -822,7 +822,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasRelate(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
|
@ -98,6 +98,12 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
error: &SelectionError<'tcx>,
|
||||
);
|
||||
|
||||
fn emit_specialized_closure_kind_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Option<ErrorGuaranteed>;
|
||||
|
||||
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool;
|
||||
|
||||
fn report_const_param_not_wf(
|
||||
@ -411,6 +417,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
|
||||
let trait_predicate = bound_predicate.rebind(trait_predicate);
|
||||
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
|
||||
if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME(effects)
|
||||
let predicate_is_const = false;
|
||||
@ -425,7 +436,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
// reported on the binding definition (#56607).
|
||||
return;
|
||||
}
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
let (post_message, pre_message, type_def, file_note) = self
|
||||
.get_parent_trait_ref(obligation.cause.code())
|
||||
.map(|(t, s)| {
|
||||
@ -786,11 +796,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
report_object_safety_error(self.tcx, span, trait_def_id, violations)
|
||||
}
|
||||
|
||||
ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
|
||||
let found_kind = self.closure_kind(closure_args).unwrap();
|
||||
self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
match self.tcx.sess.opts.unstable_opts.trait_solver {
|
||||
@ -927,6 +932,38 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn emit_specialized_closure_kind_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind()
|
||||
&& let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id())
|
||||
&& let Some(found_kind) = self.closure_kind(closure_args)
|
||||
&& !found_kind.extends(expected_kind)
|
||||
&& let sig = closure_args.as_closure().sig()
|
||||
&& self.can_sub(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
sig.map_bound(|sig| {
|
||||
ty::TraitRef::new(
|
||||
self.tcx,
|
||||
trait_ref.def_id(),
|
||||
[trait_ref.self_ty().skip_binder(), sig.inputs()[0]],
|
||||
)
|
||||
}),
|
||||
)
|
||||
{
|
||||
let mut err =
|
||||
self.report_closure_error(&obligation, closure_def_id, found_kind, expected_kind);
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
Some(err.emit())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool {
|
||||
if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
|
@ -350,7 +350,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
|
||||
| ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
@ -411,19 +410,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
|
||||
match self.selcx.infcx.closure_kind(closure_args) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
ProcessResult::Changed(vec![])
|
||||
} else {
|
||||
ProcessResult::Error(CodeSelectionError(Unimplemented))
|
||||
}
|
||||
}
|
||||
None => ProcessResult::Unchanged,
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
match wf::obligations(
|
||||
self.selcx.infcx,
|
||||
|
@ -130,7 +130,6 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
|
@ -288,8 +288,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind not yet known");
|
||||
candidates.vec.push(ClosureCandidate { is_const });
|
||||
if kind == ty::ClosureKind::FnOnce {
|
||||
candidates.vec.push(ClosureCandidate { is_const });
|
||||
} else {
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -821,11 +821,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||
let kind = self
|
||||
.tcx()
|
||||
.fn_trait_kind_from_def_id(obligation.predicate.def_id())
|
||||
.unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
|
||||
|
||||
// Okay to skip binder because the args on closure types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters.
|
||||
@ -835,15 +830,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
|
||||
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
|
||||
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
|
||||
|
||||
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
|
||||
|
||||
nested.push(obligation.with(
|
||||
self.tcx(),
|
||||
ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
|
||||
));
|
||||
|
||||
Ok(nested)
|
||||
}
|
||||
|
||||
|
@ -885,19 +885,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
|
||||
match self.infcx.closure_kind(closure_args) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
Ok(EvaluatedToOk)
|
||||
} else {
|
||||
Ok(EvaluatedToErr)
|
||||
}
|
||||
}
|
||||
None => Ok(EvaluatedToAmbig),
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
|
||||
match const_evaluatable::is_const_evaluatable(
|
||||
self.infcx,
|
||||
|
@ -58,7 +58,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
|
||||
| ty::PredicateKind::AliasRelate(..)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
|
@ -129,11 +129,6 @@ pub enum PredicateKind<I: Interner> {
|
||||
/// Trait must be object-safe.
|
||||
ObjectSafe(I::DefId),
|
||||
|
||||
/// No direct syntax. May be thought of as `where T: FnFoo<...>`
|
||||
/// for some generic args `...` and `T` being a closure type.
|
||||
/// Satisfied (or refuted) once we know the closure's kind.
|
||||
ClosureKind(I::DefId, I::GenericArgs, I::ClosureKind),
|
||||
|
||||
/// `T1 <: T2`
|
||||
///
|
||||
/// This obligation is created most often when we have two
|
||||
@ -173,7 +168,6 @@ where
|
||||
I::Term: Copy,
|
||||
I::CoercePredicate: Copy,
|
||||
I::SubtypePredicate: Copy,
|
||||
I::ClosureKind: Copy,
|
||||
ClauseKind<I>: Copy,
|
||||
{
|
||||
}
|
||||
@ -183,9 +177,6 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
|
||||
match (self, other) {
|
||||
(Self::Clause(l0), Self::Clause(r0)) => l0 == r0,
|
||||
(Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0,
|
||||
(Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => {
|
||||
l0 == r0 && l1 == r1 && l2 == r2
|
||||
}
|
||||
(Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0,
|
||||
(Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0,
|
||||
(Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1,
|
||||
@ -207,18 +198,12 @@ where
|
||||
I::Term: TypeFoldable<I>,
|
||||
I::CoercePredicate: TypeFoldable<I>,
|
||||
I::SubtypePredicate: TypeFoldable<I>,
|
||||
I::ClosureKind: TypeFoldable<I>,
|
||||
ClauseKind<I>: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
|
||||
PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
|
||||
PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind(
|
||||
d.try_fold_with(folder)?,
|
||||
g.try_fold_with(folder)?,
|
||||
k.try_fold_with(folder)?,
|
||||
),
|
||||
PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
|
||||
PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
@ -242,18 +227,12 @@ where
|
||||
I::Term: TypeVisitable<I>,
|
||||
I::CoercePredicate: TypeVisitable<I>,
|
||||
I::SubtypePredicate: TypeVisitable<I>,
|
||||
I::ClosureKind: TypeVisitable<I>,
|
||||
ClauseKind<I>: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match self {
|
||||
PredicateKind::Clause(p) => p.visit_with(visitor),
|
||||
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
|
||||
PredicateKind::ClosureKind(d, g, k) => {
|
||||
d.visit_with(visitor)?;
|
||||
g.visit_with(visitor)?;
|
||||
k.visit_with(visitor)
|
||||
}
|
||||
PredicateKind::Subtype(s) => s.visit_with(visitor),
|
||||
PredicateKind::Coerce(s) => s.visit_with(visitor),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
@ -313,9 +292,6 @@ impl<I: Interner> fmt::Debug for PredicateKind<I> {
|
||||
PredicateKind::ObjectSafe(trait_def_id) => {
|
||||
write!(f, "ObjectSafe({trait_def_id:?})")
|
||||
}
|
||||
PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
|
||||
write!(f, "ClosureKind({closure_def_id:?}, {closure_args:?}, {kind:?})")
|
||||
}
|
||||
PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
|
||||
PredicateKind::Ambiguous => write!(f, "Ambiguous"),
|
||||
PredicateKind::AliasRelate(t1, t2, dir) => {
|
||||
|
@ -767,7 +767,6 @@ pub struct GenericPredicates {
|
||||
pub enum PredicateKind {
|
||||
Clause(ClauseKind),
|
||||
ObjectSafe(TraitDef),
|
||||
ClosureKind(ClosureDef, GenericArgs, ClosureKind),
|
||||
SubType(SubtypePredicate),
|
||||
Coerce(CoercePredicate),
|
||||
ConstEquate(Const, Const),
|
||||
|
Loading…
Reference in New Issue
Block a user