Skip to content

Commit 295b82c

Browse files
committed
prove super trait bounds when using impls
1 parent f9873a8 commit 295b82c

File tree

4 files changed

+39
-13
lines changed

4 files changed

+39
-13
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
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,24 @@ where
190190
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
191191

192192
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
193+
// Resolve inference variables here to improve the debug output :)
194+
let impl_trait_ref = ecx.resolve_vars_if_possible(impl_trait_ref);
193195

194196
let where_clause_bounds = cx
195197
.predicates_of(impl_def_id)
196198
.iter_instantiated(cx, impl_args)
197199
.map(|pred| goal.with(cx, pred));
198200
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
199201

202+
// Unlike for trait goals, we do not need to check super traits here as they
203+
// are only implied for trait clauses. Doing so would result in an unproductive
204+
// cycle when normalizing
205+
//
206+
// trait Super<T> {}
207+
// trait Trait: Super<Self::Assoc> {
208+
// type Assoc;
209+
// }
210+
200211
// Add GAT where clauses from the trait's definition.
201212
// FIXME: We don't need these, since these are the type's own WF obligations.
202213
ecx.add_goals(

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
@@ -69,8 +69,6 @@ pub enum GoalSource {
6969
/// changes whether cycles are coinductive.
7070
ImplWhereBound,
7171
/// Const conditions that need to hold for `~const` alias bounds to hold.
72-
///
73-
/// FIXME(-Znext-solver=coinductive): Are these even coinductive?
7472
AliasBoundConstCondition,
7573
/// Instantiating a higher-ranked goal and re-proving it.
7674
InstantiateHigherRanked,

0 commit comments

Comments
 (0)