@@ -7,10 +7,10 @@ use rustc_infer::traits::solve::inspect::ProbeKind;
7
7
use rustc_infer:: traits:: solve:: { CandidateSource , GoalSource , MaybeCause } ;
8
8
use rustc_infer:: traits:: {
9
9
self , FulfillmentError , FulfillmentErrorCode , MismatchedProjectionTypes , Obligation ,
10
- PredicateObligation , SelectionError , TraitEngine ,
10
+ ObligationCause , PredicateObligation , SelectionError , TraitEngine ,
11
11
} ;
12
- use rustc_middle:: ty;
13
12
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
13
+ use rustc_middle:: ty:: { self , TyCtxt } ;
14
14
15
15
use super :: eval_ctxt:: GenerateProofTree ;
16
16
use super :: inspect:: { ProofTreeInferCtxtExt , ProofTreeVisitor } ;
@@ -219,14 +219,14 @@ fn fulfillment_error_for_no_solution<'tcx>(
219
219
}
220
220
ty:: PredicateKind :: Subtype ( pred) => {
221
221
let ( a, b) = infcx. enter_forall_and_leak_universe (
222
- root_obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
222
+ obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
223
223
) ;
224
224
let expected_found = ExpectedFound :: new ( true , a, b) ;
225
225
FulfillmentErrorCode :: SubtypeError ( expected_found, TypeError :: Sorts ( expected_found) )
226
226
}
227
227
ty:: PredicateKind :: Coerce ( pred) => {
228
228
let ( a, b) = infcx. enter_forall_and_leak_universe (
229
- root_obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
229
+ obligation . predicate . kind ( ) . rebind ( ( pred. a , pred. b ) ) ,
230
230
) ;
231
231
let expected_found = ExpectedFound :: new ( false , a, b) ;
232
232
FulfillmentErrorCode :: SubtypeError ( expected_found, TypeError :: Sorts ( expected_found) )
@@ -272,17 +272,30 @@ fn fulfillment_error_for_stalled<'tcx>(
272
272
}
273
273
}
274
274
275
+ fn find_best_leaf_obligation < ' tcx > (
276
+ infcx : & InferCtxt < ' tcx > ,
277
+ obligation : & PredicateObligation < ' tcx > ,
278
+ ) -> PredicateObligation < ' tcx > {
279
+ let obligation = infcx. resolve_vars_if_possible ( obligation. clone ( ) ) ;
280
+ infcx
281
+ . visit_proof_tree (
282
+ obligation. clone ( ) . into ( ) ,
283
+ & mut BestObligation { obligation : obligation. clone ( ) } ,
284
+ )
285
+ . break_value ( )
286
+ . unwrap_or ( obligation)
287
+ }
288
+
275
289
struct BestObligation < ' tcx > {
276
290
obligation : PredicateObligation < ' tcx > ,
277
291
}
278
292
279
293
impl < ' tcx > BestObligation < ' tcx > {
280
294
fn with_derived_obligation (
281
295
& mut self ,
282
- derive_obligation : impl FnOnce ( & mut Self ) -> PredicateObligation < ' tcx > ,
296
+ derived_obligation : PredicateObligation < ' tcx > ,
283
297
and_then : impl FnOnce ( & mut Self ) -> <Self as ProofTreeVisitor < ' tcx > >:: Result ,
284
298
) -> <Self as ProofTreeVisitor < ' tcx > >:: Result {
285
- let derived_obligation = derive_obligation ( self ) ;
286
299
let old_obligation = std:: mem:: replace ( & mut self . obligation , derived_obligation) ;
287
300
let res = and_then ( self ) ;
288
301
self . obligation = old_obligation;
@@ -298,13 +311,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
298
311
}
299
312
300
313
fn visit_goal ( & mut self , goal : & super :: inspect:: InspectGoal < ' _ , ' tcx > ) -> Self :: Result {
314
+ // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
315
+ // This most likely means that the goal just didn't unify at all, e.g. a param
316
+ // candidate with an alias in it.
301
317
let candidates = goal. candidates ( ) ;
302
- // FIXME: Throw out candidates that have no failing WC and >1 failing misc goal.
303
-
304
- // HACK:
305
- if self . obligation . recursion_depth > 3 {
306
- return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
307
- }
308
318
309
319
let [ candidate] = candidates. as_slice ( ) else {
310
320
return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
@@ -320,80 +330,71 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
320
330
let tcx = goal. infcx ( ) . tcx ;
321
331
let mut impl_where_bound_count = 0 ;
322
332
for nested_goal in candidate. instantiate_nested_goals ( self . span ( ) ) {
323
- if matches ! ( nested_goal. source( ) , GoalSource :: ImplWhereBound ) {
324
- impl_where_bound_count += 1 ;
325
- } else {
326
- continue ;
333
+ let obligation;
334
+ match nested_goal. source ( ) {
335
+ GoalSource :: Misc => {
336
+ continue ;
337
+ }
338
+ GoalSource :: ImplWhereBound => {
339
+ obligation = Obligation {
340
+ cause : derive_cause (
341
+ tcx,
342
+ candidate. kind ( ) ,
343
+ self . obligation . cause . clone ( ) ,
344
+ impl_where_bound_count,
345
+ parent_trait_pred,
346
+ ) ,
347
+ param_env : nested_goal. goal ( ) . param_env ,
348
+ predicate : nested_goal. goal ( ) . predicate ,
349
+ recursion_depth : self . obligation . recursion_depth + 1 ,
350
+ } ;
351
+ impl_where_bound_count += 1 ;
352
+ }
353
+ GoalSource :: InstantiateHigherRanked => {
354
+ obligation = self . obligation . clone ( ) ;
355
+ }
327
356
}
328
357
329
358
// Skip nested goals that hold.
359
+ //FIXME: We should change the max allowed certainty based on if we're
360
+ // visiting an ambiguity or error obligation.
330
361
if matches ! ( nested_goal. result( ) , Ok ( Certainty :: Yes ) ) {
331
362
continue ;
332
363
}
333
364
334
- self . with_derived_obligation (
335
- |self_| {
336
- let mut cause = self_. obligation . cause . clone ( ) ;
337
- cause = match candidate. kind ( ) {
338
- ProbeKind :: TraitCandidate {
339
- source : CandidateSource :: Impl ( impl_def_id) ,
340
- result : _,
341
- } => {
342
- let idx = impl_where_bound_count - 1 ;
343
- if let Some ( ( _, span) ) = tcx
344
- . predicates_of ( impl_def_id)
345
- . instantiate_identity ( tcx)
346
- . iter ( )
347
- . nth ( idx)
348
- {
349
- cause. derived_cause ( parent_trait_pred, |derived| {
350
- traits:: ImplDerivedObligation ( Box :: new (
351
- traits:: ImplDerivedObligationCause {
352
- derived,
353
- impl_or_alias_def_id : impl_def_id,
354
- impl_def_predicate_index : Some ( idx) ,
355
- span,
356
- } ,
357
- ) )
358
- } )
359
- } else {
360
- cause
361
- }
362
- }
363
- ProbeKind :: TraitCandidate {
364
- source : CandidateSource :: BuiltinImpl ( ..) ,
365
- result : _,
366
- } => {
367
- cause. derived_cause ( parent_trait_pred, traits:: BuiltinDerivedObligation )
368
- }
369
- _ => cause,
370
- } ;
371
-
372
- Obligation {
373
- cause,
374
- param_env : nested_goal. goal ( ) . param_env ,
375
- predicate : nested_goal. goal ( ) . predicate ,
376
- recursion_depth : self_. obligation . recursion_depth + 1 ,
377
- }
378
- } ,
379
- |self_| self_. visit_goal ( & nested_goal) ,
380
- ) ?;
365
+ self . with_derived_obligation ( obligation, |this| nested_goal. visit_with ( this) ) ?;
381
366
}
382
367
383
368
ControlFlow :: Break ( self . obligation . clone ( ) )
384
369
}
385
370
}
386
371
387
- fn find_best_leaf_obligation < ' tcx > (
388
- infcx : & InferCtxt < ' tcx > ,
389
- obligation : & PredicateObligation < ' tcx > ,
390
- ) -> PredicateObligation < ' tcx > {
391
- let obligation = infcx. resolve_vars_if_possible ( obligation. clone ( ) ) ;
392
- infcx
393
- . visit_proof_tree (
394
- obligation. clone ( ) . into ( ) ,
395
- & mut BestObligation { obligation : obligation. clone ( ) } ,
396
- )
397
- . break_value ( )
398
- . unwrap_or ( obligation)
372
+ fn derive_cause < ' tcx > (
373
+ tcx : TyCtxt < ' tcx > ,
374
+ candidate_kind : ProbeKind < ' tcx > ,
375
+ mut cause : ObligationCause < ' tcx > ,
376
+ idx : usize ,
377
+ parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
378
+ ) -> ObligationCause < ' tcx > {
379
+ match candidate_kind {
380
+ ProbeKind :: TraitCandidate { source : CandidateSource :: Impl ( impl_def_id) , result : _ } => {
381
+ if let Some ( ( _, span) ) =
382
+ tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) . iter ( ) . nth ( idx)
383
+ {
384
+ cause = cause. derived_cause ( parent_trait_pred, |derived| {
385
+ traits:: ImplDerivedObligation ( Box :: new ( traits:: ImplDerivedObligationCause {
386
+ derived,
387
+ impl_or_alias_def_id : impl_def_id,
388
+ impl_def_predicate_index : Some ( idx) ,
389
+ span,
390
+ } ) )
391
+ } )
392
+ }
393
+ }
394
+ ProbeKind :: TraitCandidate { source : CandidateSource :: BuiltinImpl ( ..) , result : _ } => {
395
+ cause = cause. derived_cause ( parent_trait_pred, traits:: BuiltinDerivedObligation ) ;
396
+ }
397
+ _ => { }
398
+ } ;
399
+ cause
399
400
}
0 commit comments