Skip to content

Commit 51090b9

Browse files
committed
show normalizes-to hack and response instantiation goals
1 parent e367c04 commit 51090b9

File tree

4 files changed

+71
-18
lines changed

4 files changed

+71
-18
lines changed

compiler/rustc_middle/src/traits/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -991,3 +991,9 @@ pub enum DefiningAnchor {
991991
/// Used to catch type mismatch errors when handling opaque types.
992992
Error,
993993
}
994+
995+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
996+
pub enum IsNormalizesToHack {
997+
Yes,
998+
No,
999+
}

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

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{CanonicalInput, Certainty, Goal, NoSolution, QueryInput, QueryResult};
2-
use crate::ty;
2+
use crate::{traits::IsNormalizesToHack, ty};
33
use std::fmt::{Debug, Write};
44

55
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
@@ -14,6 +14,8 @@ pub struct GoalEvaluation<'tcx> {
1414
pub canonicalized_goal: CanonicalInput<'tcx>,
1515

1616
pub kind: GoalEvaluationKind<'tcx>,
17+
pub is_normalizes_to_hack: IsNormalizesToHack,
18+
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
1719

1820
pub result: QueryResult<'tcx>,
1921
}
@@ -99,7 +101,13 @@ impl ProofTreeFormatter<'_, '_> {
99101

100102
fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
101103
let f = &mut *self.f;
102-
writeln!(f, "GOAL: {:?}", goal.uncanonicalized_goal)?;
104+
105+
let goal_text = match goal.is_normalizes_to_hack {
106+
IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
107+
IsNormalizesToHack::No => "GOAL",
108+
};
109+
110+
writeln!(f, "{}: {:?}", goal_text, goal.uncanonicalized_goal,)?;
103111
writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
104112

105113
match &goal.kind {
@@ -120,7 +128,19 @@ impl ProofTreeFormatter<'_, '_> {
120128
let f = &mut *self.f;
121129
writeln!(f, "RESULT: {:?}", goal.result)
122130
}
131+
}?;
132+
133+
if goal.returned_goals.len() > 0 {
134+
let f = &mut *self.f;
135+
writeln!(f, "NESTED GOALS ADDED TO CALLER: [")?;
136+
let mut f = self.nested();
137+
for goal in goal.returned_goals.iter() {
138+
writeln!(f, "ADDED GOAL: {:?},", goal)?;
139+
}
140+
writeln!(self.f, "]")?;
123141
}
142+
143+
Ok(())
124144
}
125145

126146
fn format_evaluation_step(

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::traits::solve::{
1414
CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
1515
PredefinedOpaquesData, QueryResult,
1616
};
17-
use rustc_middle::traits::DefiningAnchor;
17+
use rustc_middle::traits::{DefiningAnchor, IsNormalizesToHack};
1818
use rustc_middle::ty::{
1919
self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
2020
TypeVisitableExt, TypeVisitor,
@@ -79,12 +79,6 @@ pub struct EvalCtxt<'a, 'tcx> {
7979
inspect: ProofTreeBuilder<'tcx>,
8080
}
8181

82-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
83-
pub(super) enum IsNormalizesToHack {
84-
Yes,
85-
No,
86-
}
87-
8882
#[derive(Debug, Clone)]
8983
pub(super) struct NestedGoals<'tcx> {
9084
/// This normalizes-to goal that is treated specially during the evaluation
@@ -262,24 +256,37 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
262256
goal: Goal<'tcx, ty::Predicate<'tcx>>,
263257
) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
264258
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
265-
let mut goal_evaluation = self.inspect.new_goal_evaluation(goal);
259+
let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, is_normalizes_to_hack);
266260
let canonical_response = EvalCtxt::evaluate_canonical_goal(
267261
self.tcx(),
268262
self.search_graph,
269263
canonical_goal,
270264
&mut goal_evaluation,
271265
);
272266
goal_evaluation.query_result(canonical_response);
273-
self.inspect.goal_evaluation(goal_evaluation);
274-
let canonical_response = canonical_response?;
267+
let canonical_response = match canonical_response {
268+
Err(e) => {
269+
self.inspect.goal_evaluation(goal_evaluation);
270+
return Err(e);
271+
}
272+
Ok(response) => response,
273+
};
275274

276275
let has_changed = !canonical_response.value.var_values.is_identity()
277276
|| !canonical_response.value.external_constraints.opaque_types.is_empty();
278-
let (certainty, nested_goals) = self.instantiate_and_apply_query_response(
277+
let (certainty, nested_goals) = match self.instantiate_and_apply_query_response(
279278
goal.param_env,
280279
orig_values,
281280
canonical_response,
282-
)?;
281+
) {
282+
Err(e) => {
283+
self.inspect.goal_evaluation(goal_evaluation);
284+
return Err(e);
285+
}
286+
Ok(response) => response,
287+
};
288+
goal_evaluation.returned_goals(&nested_goals);
289+
self.inspect.goal_evaluation(goal_evaluation);
283290

284291
if !has_changed && !nested_goals.is_empty() {
285292
bug!("an unchanged goal shouldn't have any side-effects on instantiation");

compiler/rustc_trait_selection/src/solve/inspect.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_middle::{
55
inspect::{self, CacheHit, CandidateKind},
66
CanonicalInput, Certainty, Goal, QueryInput, QueryResult,
77
},
8+
IsNormalizesToHack,
89
},
910
ty,
1011
};
@@ -17,6 +18,8 @@ pub struct WipGoalEvaluation<'tcx> {
1718
pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
1819

1920
pub cache_hit: Option<CacheHit>,
21+
pub is_normalizes_to_hack: IsNormalizesToHack,
22+
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
2023

2124
pub result: Option<QueryResult<'tcx>>,
2225
}
@@ -35,6 +38,8 @@ impl<'tcx> WipGoalEvaluation<'tcx> {
3538
.collect(),
3639
},
3740
},
41+
is_normalizes_to_hack: self.is_normalizes_to_hack,
42+
returned_goals: self.returned_goals,
3843
result: self.result.unwrap(),
3944
}
4045
}
@@ -116,13 +121,11 @@ pub enum DebugSolver<'tcx> {
116121
pub struct ProofTreeBuilder<'tcx>(Option<Box<DebugSolver<'tcx>>>);
117122
impl<'tcx> ProofTreeBuilder<'tcx> {
118123
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
119-
let wip_tree = *(self.0?);
120-
121-
match wip_tree {
124+
match *(self.0?) {
122125
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
123126
Some(wip_goal_evaluation.finalize())
124127
}
125-
_ => unreachable!(),
128+
root => unreachable!("unexpected proof tree builder root node: {:?}", root),
126129
}
127130
}
128131

@@ -141,6 +144,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
141144
pub fn new_goal_evaluation(
142145
&mut self,
143146
goal: Goal<'tcx, ty::Predicate<'tcx>>,
147+
is_normalizes_to_hack: IsNormalizesToHack,
144148
) -> ProofTreeBuilder<'tcx> {
145149
if self.0.is_none() {
146150
return ProofTreeBuilder(None);
@@ -150,7 +154,9 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
150154
uncanonicalized_goal: goal,
151155
canonicalized_goal: None,
152156
evaluation_steps: vec![],
157+
is_normalizes_to_hack,
153158
cache_hit: None,
159+
returned_goals: vec![],
154160
result: None,
155161
}))))
156162
}
@@ -181,6 +187,20 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
181187
_ => unreachable!(),
182188
};
183189
}
190+
pub fn returned_goals(&mut self, goals: &[Goal<'tcx, ty::Predicate<'tcx>>]) {
191+
let this = match self.0.as_mut() {
192+
None => return,
193+
Some(this) => &mut **this,
194+
};
195+
196+
match this {
197+
DebugSolver::GoalEvaluation(evaluation) => {
198+
assert!(evaluation.returned_goals.is_empty());
199+
evaluation.returned_goals.extend(goals);
200+
}
201+
_ => unreachable!(),
202+
}
203+
}
184204
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
185205
let this = match self.0.as_mut() {
186206
None => return,

0 commit comments

Comments
 (0)