@@ -146,6 +146,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
146
146
/// inference constraints, and optionally the args of an impl if this candidate
147
147
/// came from a `CandidateSource::Impl`. This function modifies the state of the
148
148
/// `infcx`.
149
+ #[ instrument(
150
+ level = "debug" ,
151
+ skip_all,
152
+ fields( goal = ?self . goal. goal, nested_goals = ?self . nested_goals)
153
+ ) ]
149
154
pub fn instantiate_nested_goals_and_opt_impl_args (
150
155
& self ,
151
156
span : Span ,
@@ -213,10 +218,23 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
213
218
} ;
214
219
let goal =
215
220
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 ;
220
238
InspectGoal :: new (
221
239
infcx,
222
240
self . goal . depth + 1 ,
@@ -225,13 +243,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
225
243
source,
226
244
)
227
245
}
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
+ }
235
257
} )
236
258
. collect ( ) ;
237
259
0 commit comments