Make const trait aliases work in next solver
This commit is contained in:
@@ -1031,9 +1031,11 @@ pub(super) fn const_conditions<'tcx>(
|
||||
Node::Item(item) => match item.kind {
|
||||
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
|
||||
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
|
||||
hir::ItemKind::TraitAlias(_, _, generics, supertraits)
|
||||
| hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
|
||||
(generics, Some((item.owner_id.def_id, supertraits)), false)
|
||||
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
|
||||
(generics, Some((Some(item.owner_id.def_id), supertraits)), false)
|
||||
}
|
||||
hir::ItemKind::TraitAlias(_, _, generics, supertraits) => {
|
||||
(generics, Some((None, supertraits)), false)
|
||||
}
|
||||
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
||||
},
|
||||
@@ -1090,12 +1092,14 @@ pub(super) fn const_conditions<'tcx>(
|
||||
}
|
||||
|
||||
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
|
||||
// We've checked above that the trait is conditionally const.
|
||||
bounds.push((
|
||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
||||
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
||||
DUMMY_SP,
|
||||
));
|
||||
if let Some(def_id) = def_id {
|
||||
// We've checked above that the trait is conditionally const.
|
||||
bounds.push((
|
||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
||||
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
||||
DUMMY_SP,
|
||||
));
|
||||
}
|
||||
|
||||
icx.lowerer().lower_bounds(
|
||||
tcx.types.self_param,
|
||||
|
||||
@@ -196,10 +196,35 @@ where
|
||||
}
|
||||
|
||||
fn consider_trait_alias_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
_goal: Goal<I, Self>,
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
unreachable!("trait aliases are never const")
|
||||
let cx = ecx.cx();
|
||||
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
let where_clause_bounds = cx
|
||||
.predicates_of(goal.predicate.def_id().into())
|
||||
.iter_instantiated(cx, goal.predicate.trait_ref.args)
|
||||
.map(|p| goal.with(cx, p));
|
||||
|
||||
let const_conditions = cx
|
||||
.const_conditions(goal.predicate.def_id().into())
|
||||
.iter_instantiated(cx, goal.predicate.trait_ref.args)
|
||||
.map(|bound_trait_ref| {
|
||||
goal.with(
|
||||
cx,
|
||||
bound_trait_ref.to_host_effect_clause(cx, goal.predicate.constness),
|
||||
)
|
||||
});
|
||||
// While you could think of trait aliases to have a single builtin impl
|
||||
// which uses its implied trait bounds as where-clauses, using
|
||||
// `GoalSource::ImplWhereClause` here would be incorrect, as we also
|
||||
// impl them, which means we're "stepping out of the impl constructor"
|
||||
// again. To handle this, we treat these cycles as ambiguous for now.
|
||||
ecx.add_goals(GoalSource::Misc, where_clause_bounds);
|
||||
ecx.add_goals(GoalSource::Misc, const_conditions);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_sizedness_candidates(
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
error[E0277]: the trait bound `T: [const] Baz` is not satisfied
|
||||
--> $DIR/trait_alias.rs:20:11
|
||||
--> $DIR/trait_alias.rs:22:11
|
||||
|
|
||||
LL | x.baz();
|
||||
| ^^^
|
||||
|
||||
error[E0277]: the trait bound `(): const Foo` is not satisfied
|
||||
--> $DIR/trait_alias.rs:25:19
|
||||
|
|
||||
LL | const _: () = foo(&());
|
||||
| --- ^^^
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/trait_alias.rs:16:17
|
||||
|
|
||||
LL | const fn foo<T: [const] Foo>(x: &T) {
|
||||
| ^^^^^^^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
error[E0277]: the trait bound `(): const Foo` is not satisfied
|
||||
--> $DIR/trait_alias.rs:25:19
|
||||
|
|
||||
LL | const _: () = foo(&());
|
||||
| --- ^^^
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/trait_alias.rs:16:17
|
||||
|
|
||||
LL | const fn foo<T: [const] Foo>(x: &T) {
|
||||
| ^^^^^^^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -1,5 +1,7 @@
|
||||
#![feature(trait_alias, const_trait_impl)]
|
||||
//@ revisions: pass fail
|
||||
//@ compile-flags: -Znext-solver
|
||||
//@[pass] check-pass
|
||||
|
||||
const trait Bar {
|
||||
fn bar(&self) {}
|
||||
@@ -23,6 +25,5 @@ const fn foo<T: [const] Foo>(x: &T) {
|
||||
}
|
||||
|
||||
const _: () = foo(&());
|
||||
//~^ ERROR: `(): const Foo` is not satisfied
|
||||
|
||||
fn main() {}
|
||||
|
||||
Reference in New Issue
Block a user