Skip to content

Commit ed00f66

Browse files
authored
Rollup merge of rust-lang#124540 - compiler-errors:nested-goals, r=lcnr
Give proof tree visitors the ability to instantiate nested goals directly Useful when we want to look at the nested goals but not necessarily visit them (e.g. in select). r? lcnr
2 parents ea3d99e + 7597d15 commit ed00f66

File tree

2 files changed

+57
-53
lines changed

2 files changed

+57
-53
lines changed

compiler/rustc_middle/src/traits/solve/inspect.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ pub struct GoalEvaluation<'tcx> {
6060
pub evaluation: CanonicalGoalEvaluation<'tcx>,
6161
}
6262

63-
#[derive(Eq, PartialEq)]
63+
#[derive(Eq, PartialEq, Debug)]
6464
pub struct CanonicalGoalEvaluation<'tcx> {
6565
pub goal: CanonicalInput<'tcx>,
6666
pub kind: CanonicalGoalEvaluationKind<'tcx>,
6767
pub result: QueryResult<'tcx>,
6868
}
6969

70-
#[derive(Eq, PartialEq)]
70+
#[derive(Eq, PartialEq, Debug)]
7171
pub enum CanonicalGoalEvaluationKind<'tcx> {
7272
Overflow,
7373
CycleInStack,
@@ -86,7 +86,7 @@ pub struct AddedGoalsEvaluation<'tcx> {
8686
pub result: Result<Certainty, NoSolution>,
8787
}
8888

89-
#[derive(Eq, PartialEq)]
89+
#[derive(Eq, PartialEq, Debug)]
9090
pub struct GoalEvaluationStep<'tcx> {
9191
pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
9292

compiler/rustc_trait_selection/src/solve/inspect/analyse.rs

+54-50
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ pub struct InspectConfig {
3434
pub struct InspectGoal<'a, 'tcx> {
3535
infcx: &'a InferCtxt<'tcx>,
3636
depth: usize,
37-
orig_values: &'a [ty::GenericArg<'tcx>],
37+
orig_values: Vec<ty::GenericArg<'tcx>>,
3838
goal: Goal<'tcx, ty::Predicate<'tcx>>,
39-
evaluation: &'a inspect::GoalEvaluation<'tcx>,
39+
evaluation: inspect::CanonicalGoalEvaluation<'tcx>,
4040
}
4141

4242
pub struct InspectCandidate<'a, 'tcx> {
@@ -57,6 +57,10 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
5757
self.result.map(|c| c.value.certainty)
5858
}
5959

60+
pub fn goal(&self) -> &'a InspectGoal<'a, 'tcx> {
61+
self.goal
62+
}
63+
6064
/// Certainty passed into `evaluate_added_goals_and_make_canonical_response`.
6165
///
6266
/// If this certainty is `Yes`, then we must be confident that the candidate
@@ -74,46 +78,55 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
7478
/// the state of the `infcx`.
7579
pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
7680
if self.goal.depth < visitor.config().max_depth {
77-
let infcx = self.goal.infcx;
78-
let param_env = self.goal.goal.param_env;
79-
let mut orig_values = self.goal.orig_values.to_vec();
80-
let mut instantiated_goals = vec![];
81-
for goal in &self.nested_goals {
82-
let goal = canonical::instantiate_canonical_state(
81+
for goal in self.instantiate_nested_goals(visitor.span()) {
82+
try_visit!(visitor.visit_goal(&goal));
83+
}
84+
}
85+
86+
V::Result::output()
87+
}
88+
89+
/// Instantiate the nested goals for the candidate without rolling back their
90+
/// inference constraints. This function modifies the state of the `infcx`.
91+
pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
92+
let infcx = self.goal.infcx;
93+
let param_env = self.goal.goal.param_env;
94+
let mut orig_values = self.goal.orig_values.to_vec();
95+
let instantiated_goals: Vec<_> = self
96+
.nested_goals
97+
.iter()
98+
.map(|goal| {
99+
canonical::instantiate_canonical_state(
83100
infcx,
84-
visitor.span(),
101+
span,
85102
param_env,
86103
&mut orig_values,
87104
*goal,
88-
);
89-
instantiated_goals.push(goal);
90-
}
105+
)
106+
})
107+
.collect();
91108

92-
let () = canonical::instantiate_canonical_state(
93-
infcx,
94-
visitor.span(),
95-
param_env,
96-
&mut orig_values,
97-
self.final_state,
98-
);
109+
let () = canonical::instantiate_canonical_state(
110+
infcx,
111+
span,
112+
param_env,
113+
&mut orig_values,
114+
self.final_state,
115+
);
99116

100-
for &goal in &instantiated_goals {
117+
instantiated_goals
118+
.into_iter()
119+
.map(|goal| {
101120
let proof_tree = match goal.predicate.kind().no_bound_vars() {
102121
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
103122
let unconstrained_term = match term.unpack() {
104123
ty::TermKind::Ty(_) => infcx
105-
.next_ty_var(TypeVariableOrigin {
106-
param_def_id: None,
107-
span: visitor.span(),
108-
})
124+
.next_ty_var(TypeVariableOrigin { param_def_id: None, span })
109125
.into(),
110126
ty::TermKind::Const(ct) => infcx
111127
.next_const_var(
112128
ct.ty(),
113-
ConstVariableOrigin {
114-
param_def_id: None,
115-
span: visitor.span(),
116-
},
129+
ConstVariableOrigin { param_def_id: None, span },
117130
)
118131
.into(),
119132
};
@@ -129,22 +142,16 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
129142
})
130143
.1;
131144
let InferOk { value: (), obligations: _ } = infcx
132-
.at(&ObligationCause::dummy(), param_env)
145+
.at(&ObligationCause::dummy_with_span(span), param_env)
133146
.eq(DefineOpaqueTypes::Yes, term, unconstrained_term)
134147
.unwrap();
135148
proof_tree
136149
}
137150
_ => infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1,
138151
};
139-
try_visit!(visitor.visit_goal(&InspectGoal::new(
140-
infcx,
141-
self.goal.depth + 1,
142-
&proof_tree.unwrap(),
143-
)));
144-
}
145-
}
146-
147-
V::Result::output()
152+
InspectGoal::new(infcx, self.goal.depth + 1, proof_tree.unwrap())
153+
})
154+
.collect()
148155
}
149156

150157
/// Visit all nested goals of this candidate, rolling back
@@ -164,7 +171,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
164171
}
165172

166173
pub fn result(&self) -> Result<Certainty, NoSolution> {
167-
self.evaluation.evaluation.result.map(|c| c.value.certainty)
174+
self.evaluation.result.map(|c| c.value.certainty)
168175
}
169176

170177
fn candidates_recur(
@@ -221,7 +228,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
221228

222229
pub fn candidates(&'a self) -> Vec<InspectCandidate<'a, 'tcx>> {
223230
let mut candidates = vec![];
224-
let last_eval_step = match self.evaluation.evaluation.kind {
231+
let last_eval_step = match self.evaluation.kind {
225232
inspect::CanonicalGoalEvaluationKind::Overflow
226233
| inspect::CanonicalGoalEvaluationKind::CycleInStack
227234
| inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit => {
@@ -254,18 +261,15 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
254261
candidates.pop().filter(|_| candidates.is_empty())
255262
}
256263

257-
fn new(
258-
infcx: &'a InferCtxt<'tcx>,
259-
depth: usize,
260-
root: &'a inspect::GoalEvaluation<'tcx>,
261-
) -> Self {
262-
match root.kind {
263-
inspect::GoalEvaluationKind::Root { ref orig_values } => InspectGoal {
264+
fn new(infcx: &'a InferCtxt<'tcx>, depth: usize, root: inspect::GoalEvaluation<'tcx>) -> Self {
265+
let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root;
266+
match kind {
267+
inspect::GoalEvaluationKind::Root { orig_values } => InspectGoal {
264268
infcx,
265269
depth,
266270
orig_values,
267-
goal: root.uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)),
268-
evaluation: root,
271+
goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)),
272+
evaluation,
269273
},
270274
inspect::GoalEvaluationKind::Nested { .. } => unreachable!(),
271275
}
@@ -294,6 +298,6 @@ impl<'tcx> InferCtxt<'tcx> {
294298
) -> V::Result {
295299
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
296300
let proof_tree = proof_tree.unwrap();
297-
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
301+
visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree))
298302
}
299303
}

0 commit comments

Comments
 (0)