Skip to content

Commit 4847609

Browse files
committed
prove super trait bounds when using impls
1 parent e19ea54 commit 4847609

File tree

4 files changed

+39
-14
lines changed

4 files changed

+39
-14
lines changed

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

+15
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,27 @@ where
154154
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
155155

156156
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
157+
// Resolve inference variables here to improve the debug output :)
158+
let impl_trait_ref = ecx.resolve_vars_if_possible(impl_trait_ref);
159+
157160
let where_clause_bounds = cx
158161
.predicates_of(impl_def_id)
159162
.iter_instantiated(cx, impl_args)
160163
.map(|pred| goal.with(cx, pred));
161164
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
162165

166+
// When using an impl, we have to check that its super trait bounds are actually satisfied.
167+
// This is necessary as otherwise the impl `impl<T: Magic> Magic for T` would allow us to
168+
// incorrectly assume all super traits of `Magic`.
169+
for clause in elaborate::elaborate(
170+
cx,
171+
cx.explicit_super_predicates_of(impl_trait_ref.def_id)
172+
.iter_instantiated(cx, impl_trait_ref.args)
173+
.map(|(pred, _)| pred),
174+
) {
175+
ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
176+
}
177+
163178
// For this impl to be `const`, we need to check its `~const` bounds too.
164179
let const_conditions = cx
165180
.const_conditions(impl_def_id)

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,24 @@ where
228228
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
229229

230230
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
231+
// Resolve inference variables here to improve the debug output :)
232+
let impl_trait_ref = ecx.resolve_vars_if_possible(impl_trait_ref);
231233

232234
let where_clause_bounds = cx
233235
.predicates_of(impl_def_id)
234236
.iter_instantiated(cx, impl_args)
235237
.map(|pred| goal.with(cx, pred));
236238
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
237239

240+
// Unlike for trait goals, we do not need to check super traits here as they
241+
// are only implied for trait clauses. Doing so would result in an unproductive
242+
// cycle when normalizing
243+
//
244+
// trait Super<T> {}
245+
// trait Trait: Super<Self::Assoc> {
246+
// type Assoc;
247+
// }
248+
238249
// Add GAT where clauses from the trait's definition.
239250
// FIXME: We don't need these, since these are the type's own WF obligations.
240251
ecx.add_goals(
@@ -618,7 +629,6 @@ where
618629
cx.require_lang_item(TraitSolverLangItem::Sized),
619630
[I::GenericArg::from(goal.predicate.self_ty())],
620631
);
621-
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
622632
ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate));
623633
Ty::new_unit(cx)
624634
}

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -92,23 +92,25 @@ where
9292
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
9393

9494
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
95+
// Resolve inference variables here to improve the debug output :)
96+
let impl_trait_ref = ecx.resolve_vars_if_possible(impl_trait_ref);
97+
9598
let where_clause_bounds = cx
9699
.predicates_of(impl_def_id)
97100
.iter_instantiated(cx, impl_args)
98101
.map(|pred| goal.with(cx, pred));
99102
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
100103

101-
// We currently elaborate all supertrait outlives obligations from impls.
102-
// This can be removed when we actually do coinduction correctly, and prove
103-
// all supertrait obligations unconditionally.
104-
let goal_clause: I::Clause = goal.predicate.upcast(cx);
105-
for clause in elaborate::elaborate(cx, [goal_clause]) {
106-
if matches!(
107-
clause.kind().skip_binder(),
108-
ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..)
109-
) {
110-
ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
111-
}
104+
// When using an impl, we have to check that its super trait bounds are actually satisfied.
105+
// This is necessary as otherwise the impl `impl<T: Magic> Magic for T` would allow us to
106+
// incorrectly assume all super traits of `Magic`.
107+
for clause in elaborate::elaborate(
108+
cx,
109+
cx.explicit_super_predicates_of(impl_trait_ref.def_id)
110+
.iter_instantiated(cx, impl_trait_ref.args)
111+
.map(|(pred, _)| pred),
112+
) {
113+
ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
112114
}
113115

114116
ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)

compiler/rustc_type_ir/src/solve/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ pub enum GoalSource {
7272
/// changes whether cycles are coinductive.
7373
ImplWhereBound,
7474
/// Const conditions that need to hold for `~const` alias bounds to hold.
75-
///
76-
/// FIXME(-Znext-solver=coinductive): Are these even coinductive?
7775
AliasBoundConstCondition,
7876
/// Instantiating a higher-ranked goal and re-proving it.
7977
InstantiateHigherRanked,

0 commit comments

Comments
 (0)