@@ -146,6 +146,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
146146 /// inference constraints, and optionally the args of an impl if this candidate
147147 /// came from a `CandidateSource::Impl`. This function modifies the state of the
148148 /// `infcx`.
149+ #[ instrument(
150+ level = "debug" ,
151+ skip_all,
152+ fields( goal = ?self . goal. goal, nested_goals = ?self . nested_goals)
153+ ) ]
149154 pub fn instantiate_nested_goals_and_opt_impl_args (
150155 & self ,
151156 span : Span ,
@@ -213,10 +218,23 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
213218 } ;
214219 let goal =
215220 goal. with ( infcx. tcx , ty:: NormalizesTo { alias, term : unconstrained_term } ) ;
216- let proof_tree = EvalCtxt :: enter_root ( infcx, GenerateProofTree :: Yes , |ecx| {
217- ecx. evaluate_goal_raw ( GoalEvaluationKind :: Root , GoalSource :: Misc , goal)
218- } )
219- . 1 ;
221+ // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
222+ // expected term. This means that candidates which only fail due to nested goals
223+ // and which normalize to a different term then the final result could ICE: when
224+ // building their proof tree, the expected term was unconstrained, but when
225+ // instantiating the candidate it is already constrained to the result of another
226+ // candidate.
227+ let proof_tree = infcx
228+ . probe ( |_| {
229+ EvalCtxt :: enter_root ( infcx, GenerateProofTree :: Yes , |ecx| {
230+ ecx. evaluate_goal_raw (
231+ GoalEvaluationKind :: Root ,
232+ GoalSource :: Misc ,
233+ goal,
234+ )
235+ } )
236+ } )
237+ . 1 ;
220238 InspectGoal :: new (
221239 infcx,
222240 self . goal . depth + 1 ,
@@ -225,13 +243,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
225243 source,
226244 )
227245 }
228- _ => InspectGoal :: new (
229- infcx,
230- self . goal . depth + 1 ,
231- infcx. evaluate_root_goal ( goal, GenerateProofTree :: Yes ) . 1 . unwrap ( ) ,
232- None ,
233- source,
234- ) ,
246+ _ => {
247+ // We're using a probe here as evaluating a goal could constrain
248+ // inference variables by choosing one candidate. If we then recurse
249+ // into another candidate who ends up with different inference
250+ // constraints, we get an ICE if we already applied the constraints
251+ // from the chosen candidate.
252+ let proof_tree = infcx
253+ . probe ( |_| infcx. evaluate_root_goal ( goal, GenerateProofTree :: Yes ) . 1 )
254+ . unwrap ( ) ;
255+ InspectGoal :: new ( infcx, self . goal . depth + 1 , proof_tree, None , source)
256+ }
235257 } )
236258 . collect ( ) ;
237259
0 commit comments