@@ -244,16 +244,23 @@ fn fulfillment_error_for_no_solution<'tcx>(
244
244
245
245
fn fulfillment_error_for_stalled < ' tcx > (
246
246
infcx : & InferCtxt < ' tcx > ,
247
- obligation : PredicateObligation < ' tcx > ,
247
+ root_obligation : PredicateObligation < ' tcx > ,
248
248
) -> FulfillmentError < ' tcx > {
249
- let code = infcx. probe ( |_| {
250
- match infcx. evaluate_root_goal ( obligation . clone ( ) . into ( ) , GenerateProofTree :: Never ) . 0 {
249
+ let ( code, refine_obligation ) = infcx. probe ( |_| {
250
+ match infcx. evaluate_root_goal ( root_obligation . clone ( ) . into ( ) , GenerateProofTree :: Never ) . 0 {
251
251
Ok ( ( _, Certainty :: Maybe ( MaybeCause :: Ambiguity ) ) ) => {
252
- FulfillmentErrorCode :: Ambiguity { overflow : None }
253
- }
254
- Ok ( ( _, Certainty :: Maybe ( MaybeCause :: Overflow { suggest_increasing_limit } ) ) ) => {
255
- FulfillmentErrorCode :: Ambiguity { overflow : Some ( suggest_increasing_limit) }
252
+ ( FulfillmentErrorCode :: Ambiguity { overflow : None } , true )
256
253
}
254
+ Ok ( ( _, Certainty :: Maybe ( MaybeCause :: Overflow { suggest_increasing_limit } ) ) ) => (
255
+ FulfillmentErrorCode :: Ambiguity { overflow : Some ( suggest_increasing_limit) } ,
256
+ // Don't look into overflows because we treat overflows weirdly anyways.
257
+ // In `instantiate_response_discarding_overflow` we set `has_changed = false`,
258
+ // recomputing the goal again during `find_best_leaf_obligation` may apply
259
+ // inference guidance that makes other goals go from ambig -> pass, for example.
260
+ //
261
+ // FIXME: We should probably just look into overflows here.
262
+ false ,
263
+ ) ,
257
264
Ok ( ( _, Certainty :: Yes ) ) => {
258
265
bug ! ( "did not expect successful goal when collecting ambiguity errors" )
259
266
}
@@ -264,9 +271,13 @@ fn fulfillment_error_for_stalled<'tcx>(
264
271
} ) ;
265
272
266
273
FulfillmentError {
267
- obligation : find_best_leaf_obligation ( infcx, & obligation, true ) ,
274
+ obligation : if refine_obligation {
275
+ find_best_leaf_obligation ( infcx, & root_obligation, true )
276
+ } else {
277
+ root_obligation. clone ( )
278
+ } ,
268
279
code,
269
- root_obligation : obligation ,
280
+ root_obligation,
270
281
}
271
282
}
272
283
@@ -302,41 +313,50 @@ impl<'tcx> BestObligation<'tcx> {
302
313
res
303
314
}
304
315
305
- /// Filter out the candidates that aren't either error or ambiguous (depending
306
- /// on what we are looking for), and also throw out candidates that have no
307
- /// failing WC (or higher-ranked obligations, for which there should only be
308
- /// one candidate anyways -- but I digress). This most likely means that the
309
- /// goal just didn't unify at all, e.g. a param candidate with an alias in it.
316
+ /// Filter out the candidates that aren't interesting to visit for the
317
+ /// purposes of reporting errors. For ambiguities, we only consider
318
+ /// candidates that may hold. For errors, we only consider candidates that
319
+ /// *don't* hold and which have impl-where clauses that also don't hold.
310
320
fn non_trivial_candidates < ' a > (
311
321
& self ,
312
322
goal : & ' a InspectGoal < ' a , ' tcx > ,
313
323
) -> Vec < InspectCandidate < ' a , ' tcx > > {
314
- let mut candidates = goal
315
- . candidates ( )
316
- . into_iter ( )
317
- . filter ( |candidate| match self . consider_ambiguities {
318
- true => matches ! ( candidate. result( ) , Ok ( Certainty :: Maybe ( _) ) ) ,
319
- false => matches ! ( candidate. result( ) , Err ( _) ) ,
320
- } )
321
- . collect :: < Vec < _ > > ( ) ;
322
-
323
- // If we have >1 candidate, one may still be due to "boring" reasons, like
324
- // an alias-relate that failed to hold when deeply evaluated. We really
325
- // don't care about reasons like this.
326
- if candidates. len ( ) > 1 {
327
- candidates. retain ( |candidate| {
328
- goal. infcx ( ) . probe ( |_| {
329
- candidate. instantiate_nested_goals ( self . span ( ) ) . iter ( ) . any ( |nested_goal| {
330
- matches ! (
331
- nested_goal. source( ) ,
332
- GoalSource :: ImplWhereBound | GoalSource :: InstantiateHigherRanked
333
- ) && match self . consider_ambiguities {
334
- true => matches ! ( nested_goal. result( ) , Ok ( Certainty :: Maybe ( _) ) ) ,
335
- false => matches ! ( nested_goal. result( ) , Err ( _) ) ,
336
- }
337
- } )
338
- } )
339
- } ) ;
324
+ let mut candidates = goal. candidates ( ) ;
325
+ match self . consider_ambiguities {
326
+ true => {
327
+ // If we have an ambiguous obligation, we must consider *all* candidates
328
+ // that hold, or else we may guide inference causing other goals to go
329
+ // from ambig -> pass/fail.
330
+ candidates. retain ( |candidate| candidate. result ( ) . is_ok ( ) ) ;
331
+ }
332
+ false => {
333
+ // If we have >1 candidate, one may still be due to "boring" reasons, like
334
+ // an alias-relate that failed to hold when deeply evaluated. We really
335
+ // don't care about reasons like this.
336
+ if candidates. len ( ) > 1 {
337
+ candidates. retain ( |candidate| {
338
+ goal. infcx ( ) . probe ( |_| {
339
+ candidate. instantiate_nested_goals ( self . span ( ) ) . iter ( ) . any (
340
+ |nested_goal| {
341
+ matches ! (
342
+ nested_goal. source( ) ,
343
+ GoalSource :: ImplWhereBound
344
+ | GoalSource :: InstantiateHigherRanked
345
+ ) && match self . consider_ambiguities {
346
+ true => {
347
+ matches ! (
348
+ nested_goal. result( ) ,
349
+ Ok ( Certainty :: Maybe ( MaybeCause :: Ambiguity ) )
350
+ )
351
+ }
352
+ false => matches ! ( nested_goal. result( ) , Err ( _) ) ,
353
+ }
354
+ } ,
355
+ )
356
+ } )
357
+ } ) ;
358
+ }
359
+ }
340
360
}
341
361
342
362
candidates
@@ -401,7 +421,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
401
421
402
422
// Skip nested goals that aren't the *reason* for our goal's failure.
403
423
match self . consider_ambiguities {
404
- true if matches ! ( nested_goal. result( ) , Ok ( Certainty :: Maybe ( _) ) ) => { }
424
+ true if matches ! (
425
+ nested_goal. result( ) ,
426
+ Ok ( Certainty :: Maybe ( MaybeCause :: Ambiguity ) )
427
+ ) => { }
405
428
false if matches ! ( nested_goal. result( ) , Err ( _) ) => { }
406
429
_ => continue ,
407
430
}
0 commit comments