Skip to content

Commit a2e61d3

Browse files
Canonicalize all nested goals together at once when making response
1 parent 34e91ec commit a2e61d3

File tree

8 files changed

+96
-69
lines changed

8 files changed

+96
-69
lines changed

Diff for: compiler/rustc_middle/src/traits/solve/inspect.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl Debug for Probe<'_> {
116116
pub enum ProbeStep<'tcx> {
117117
/// We added a goal to the `EvalCtxt` which will get proven
118118
/// the next time `EvalCtxt::try_evaluate_added_goals` is called.
119-
AddGoal(GoalSource, CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>),
119+
AddGoal(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>),
120120
/// The inside of a `EvalCtxt::try_evaluate_added_goals` call.
121121
EvaluateGoals(AddedGoalsEvaluation<'tcx>),
122122
/// A call to `probe` while proving the current goal. This is
@@ -128,7 +128,11 @@ pub enum ProbeStep<'tcx> {
128128
/// with the certainty of the `try_evaluate_added_goals` that is done within;
129129
/// if it's `Certainty::Yes`, then we can trust that the candidate is "finished"
130130
/// and we didn't force ambiguity for some reason.
131-
MakeCanonicalResponse { shallow_certainty: Certainty },
131+
MakeCanonicalResponse {
132+
shallow_certainty: Certainty,
133+
added_goals:
134+
CanonicalState<'tcx, &'tcx ty::List<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>>,
135+
},
132136
}
133137

134138
/// What kind of probe we're in. In case the probe represents a candidate, or

Diff for: compiler/rustc_middle/src/traits/solve/inspect/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
133133
}
134134
ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?,
135135
ProbeStep::NestedProbe(probe) => this.format_probe(probe)?,
136-
ProbeStep::MakeCanonicalResponse { shallow_certainty } => {
136+
ProbeStep::MakeCanonicalResponse { shallow_certainty, added_goals: _ } => {
137137
writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")?
138138
}
139139
}

Diff for: compiler/rustc_middle/src/ty/context.rs

+15
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ pub struct CtxtInterners<'tcx> {
157157
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
158158
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
159159
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
160+
nested_goals:
161+
InternedSet<'tcx, List<(solve::GoalSource, solve::Goal<'tcx, ty::Predicate<'tcx>>)>>,
160162
projs: InternedSet<'tcx, List<ProjectionKind>>,
161163
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
162164
const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
@@ -186,6 +188,7 @@ impl<'tcx> CtxtInterners<'tcx> {
186188
canonical_var_infos: Default::default(),
187189
predicate: Default::default(),
188190
clauses: Default::default(),
191+
nested_goals: Default::default(),
189192
projs: Default::default(),
190193
place_elems: Default::default(),
191194
const_: Default::default(),
@@ -1933,6 +1936,7 @@ slice_interners!(
19331936
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
19341937
projs: pub mk_projs(ProjectionKind),
19351938
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
1939+
nested_goals: pub mk_nested_goals((solve::GoalSource, solve::Goal<'tcx, ty::Predicate<'tcx>>)),
19361940
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
19371941
fields: pub mk_fields(FieldIdx),
19381942
local_def_ids: intern_local_def_ids(LocalDefId),
@@ -2320,6 +2324,17 @@ impl<'tcx> TyCtxt<'tcx> {
23202324
T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
23212325
}
23222326

2327+
pub fn mk_nested_goals_from_iter<I, T>(self, iter: I) -> T::Output
2328+
where
2329+
I: Iterator<Item = T>,
2330+
T: CollectAndApply<
2331+
(solve::GoalSource, solve::Goal<'tcx, ty::Predicate<'tcx>>),
2332+
&'tcx List<(solve::GoalSource, solve::Goal<'tcx, ty::Predicate<'tcx>>)>,
2333+
>,
2334+
{
2335+
T::collect_and_apply(iter, |xs| self.mk_nested_goals(xs))
2336+
}
2337+
23232338
pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
23242339
where
23252340
I: Iterator<Item = T>,

Diff for: compiler/rustc_middle/src/ty/structural_impls.rs

+12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! to help with the tedium.
55
66
use crate::mir::interpret;
7+
use crate::traits::solve;
78
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
89
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
910
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -560,6 +561,17 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
560561
}
561562
}
562563

564+
impl<'tcx> TypeFoldable<TyCtxt<'tcx>>
565+
for &'tcx ty::List<(solve::GoalSource, solve::Goal<'tcx, ty::Predicate<'tcx>>)>
566+
{
567+
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
568+
self,
569+
folder: &mut F,
570+
) -> Result<Self, F::Error> {
571+
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_nested_goals(v))
572+
}
573+
}
574+
563575
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Pattern<'tcx> {
564576
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
565577
self,

Diff for: compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
9090
&mut self,
9191
certainty: Certainty,
9292
) -> QueryResult<'tcx> {
93-
self.inspect.make_canonical_response(certainty);
93+
self.inspect.make_canonical_response(self.infcx, self.max_input_universe, certainty);
9494

9595
let goals_certainty = self.try_evaluate_added_goals()?;
9696
assert_eq!(
@@ -444,5 +444,5 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt
444444
let inspect::State { var_values, data } = state.instantiate(infcx.tcx, &instantiation);
445445

446446
EvalCtxt::unify_query_var_values(infcx, param_env, orig_values, var_values);
447-
data
447+
infcx.resolve_vars_if_possible(data)
448448
}

Diff for: compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -462,13 +462,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
462462

463463
#[instrument(level = "debug", skip(self))]
464464
pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
465-
self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
465+
self.inspect.add_normalizes_to_goal(self.tcx(), goal);
466466
self.nested_goals.normalizes_to_goals.push(goal);
467467
}
468468

469469
#[instrument(level = "debug", skip(self))]
470470
pub(super) fn add_goal(&mut self, source: GoalSource, goal: Goal<'tcx, ty::Predicate<'tcx>>) {
471-
self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
471+
self.inspect.add_goal(source, goal);
472472
self.nested_goals.goals.push((source, goal));
473473
}
474474

Diff for: compiler/rustc_trait_selection/src/solve/inspect/analyse.rs

+26-35
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
9393
pub struct InspectCandidate<'a, 'tcx> {
9494
goal: &'a InspectGoal<'a, 'tcx>,
9595
kind: inspect::ProbeKind<'tcx>,
96-
nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
96+
nested_goals: inspect::CanonicalState<
97+
'tcx,
98+
&'tcx ty::List<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
99+
>,
97100
final_state: inspect::CanonicalState<'tcx, ()>,
98101
result: QueryResult<'tcx>,
99102
shallow_certainty: Certainty,
@@ -141,23 +144,15 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
141144
let infcx = self.goal.infcx;
142145
let param_env = self.goal.goal.param_env;
143146
let mut orig_values = self.goal.orig_values.to_vec();
144-
let instantiated_goals: Vec<_> = self
145-
.nested_goals
146-
.iter()
147-
.map(|(source, goal)| {
148-
(
149-
*source,
150-
canonical::instantiate_canonical_state(
151-
infcx,
152-
span,
153-
param_env,
154-
&mut orig_values,
155-
*goal,
156-
),
157-
)
158-
})
159-
.collect();
160-
147+
let instantiated_goals = canonical::instantiate_canonical_state(
148+
infcx,
149+
span,
150+
param_env,
151+
&mut orig_values,
152+
self.nested_goals,
153+
);
154+
// FIXME: Should we truncate orig_values back down? Any new infer vars
155+
// between `nested_goals` and `final_state` are definitely unrelated...
161156
let () = canonical::instantiate_canonical_state(
162157
infcx,
163158
span,
@@ -174,7 +169,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
174169
}
175170

176171
instantiated_goals
177-
.into_iter()
172+
.iter()
178173
.map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
179174
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
180175
let unconstrained_term = match term.unpack() {
@@ -240,27 +235,24 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
240235
fn candidates_recur(
241236
&'a self,
242237
candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
243-
nested_goals: &mut Vec<(
244-
GoalSource,
245-
inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>,
246-
)>,
247238
probe: &inspect::Probe<'tcx>,
248239
) {
249-
let mut shallow_certainty = None;
240+
let mut shallow_certainty_and_goals = None;
250241
for step in &probe.steps {
251-
match step {
252-
&inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
242+
match *step {
253243
inspect::ProbeStep::NestedProbe(ref probe) => {
254244
// Nested probes have to prove goals added in their parent
255245
// but do not leak them, so we truncate the added goals
256246
// afterwards.
257-
let num_goals = nested_goals.len();
258-
self.candidates_recur(candidates, nested_goals, probe);
259-
nested_goals.truncate(num_goals);
247+
self.candidates_recur(candidates, probe);
260248
}
261-
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
262-
assert_eq!(shallow_certainty.replace(*c), None);
249+
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty, added_goals } => {
250+
assert_eq!(
251+
shallow_certainty_and_goals.replace((shallow_certainty, added_goals)),
252+
None
253+
);
263254
}
255+
inspect::ProbeStep::AddGoal(..) => {}
264256
inspect::ProbeStep::EvaluateGoals(_) => (),
265257
}
266258
}
@@ -278,11 +270,11 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
278270
| inspect::ProbeKind::OpaqueTypeStorageLookup { result } => {
279271
// We only add a candidate if `shallow_certainty` was set, which means
280272
// that we ended up calling `evaluate_added_goals_and_make_canonical_response`.
281-
if let Some(shallow_certainty) = shallow_certainty {
273+
if let Some((shallow_certainty, nested_goals)) = shallow_certainty_and_goals {
282274
candidates.push(InspectCandidate {
283275
goal: self,
284276
kind: probe.kind,
285-
nested_goals: nested_goals.clone(),
277+
nested_goals,
286278
final_state: probe.final_state,
287279
result,
288280
shallow_certainty,
@@ -310,8 +302,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
310302
}
311303
};
312304

313-
let mut nested_goals = vec![];
314-
self.candidates_recur(&mut candidates, &mut nested_goals, &last_eval_step.evaluation);
305+
self.candidates_recur(&mut candidates, &last_eval_step.evaluation);
315306

316307
candidates
317308
}

Diff for: compiler/rustc_trait_selection/src/solve/inspect/build.rs

+32-27
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,16 @@ impl<'tcx> WipProbe<'tcx> {
238238

239239
#[derive(Eq, PartialEq, Debug)]
240240
enum WipProbeStep<'tcx> {
241-
AddGoal(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>),
241+
AddGoal(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>),
242242
EvaluateGoals(WipAddedGoalsEvaluation<'tcx>),
243243
NestedProbe(WipProbe<'tcx>),
244-
MakeCanonicalResponse { shallow_certainty: Certainty },
244+
MakeCanonicalResponse {
245+
shallow_certainty: Certainty,
246+
added_goals: inspect::CanonicalState<
247+
'tcx,
248+
&'tcx ty::List<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
249+
>,
250+
},
245251
}
246252

247253
impl<'tcx> WipProbeStep<'tcx> {
@@ -250,8 +256,8 @@ impl<'tcx> WipProbeStep<'tcx> {
250256
WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
251257
WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()),
252258
WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
253-
WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
254-
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
259+
WipProbeStep::MakeCanonicalResponse { shallow_certainty, added_goals } => {
260+
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty, added_goals }
255261
}
256262
}
257263
}
@@ -500,47 +506,46 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
500506

501507
pub fn add_normalizes_to_goal(
502508
&mut self,
503-
infcx: &InferCtxt<'tcx>,
504-
max_input_universe: ty::UniverseIndex,
509+
tcx: TyCtxt<'tcx>,
505510
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
506511
) {
507-
self.add_goal(
508-
infcx,
509-
max_input_universe,
510-
GoalSource::Misc,
511-
goal.with(infcx.tcx, goal.predicate),
512-
);
512+
self.add_goal(GoalSource::Misc, goal.with(tcx, goal.predicate));
513513
}
514514

515-
pub fn add_goal(
516-
&mut self,
517-
infcx: &InferCtxt<'tcx>,
518-
max_input_universe: ty::UniverseIndex,
519-
source: GoalSource,
520-
goal: Goal<'tcx, ty::Predicate<'tcx>>,
521-
) {
515+
pub fn add_goal(&mut self, source: GoalSource, goal: Goal<'tcx, ty::Predicate<'tcx>>) {
522516
match self.as_mut() {
523517
None => {}
524518
Some(DebugSolver::GoalEvaluationStep(state)) => {
525-
let goal = canonical::make_canonical_state(
526-
infcx,
527-
&state.var_values,
528-
max_input_universe,
529-
goal,
530-
);
531519
state.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal))
532520
}
533521
_ => bug!(),
534522
}
535523
}
536524

537-
pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
525+
pub fn make_canonical_response(
526+
&mut self,
527+
infcx: &InferCtxt<'tcx>,
528+
max_input_universe: ty::UniverseIndex,
529+
shallow_certainty: Certainty,
530+
) {
538531
match self.as_mut() {
539532
Some(DebugSolver::GoalEvaluationStep(state)) => {
533+
let added_goals = infcx.tcx.mk_nested_goals_from_iter(
534+
state.current_evaluation_scope().steps.iter().filter_map(|step| match *step {
535+
WipProbeStep::AddGoal(source, goal) => Some((source, goal)),
536+
_ => None,
537+
}),
538+
);
539+
let added_goals = canonical::make_canonical_state(
540+
infcx,
541+
&state.var_values,
542+
max_input_universe,
543+
added_goals,
544+
);
540545
state
541546
.current_evaluation_scope()
542547
.steps
543-
.push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
548+
.push(WipProbeStep::MakeCanonicalResponse { shallow_certainty, added_goals });
544549
}
545550
None => {}
546551
_ => {}

0 commit comments

Comments
 (0)