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