@@ -291,6 +291,34 @@ impl<'tcx> BestObligation<'tcx> {
291
291
}
292
292
}
293
293
294
+ /// When a higher-ranked projection goal fails, check that the corresponding
295
+ /// higher-ranked trait goal holds or not. This is because the process of
296
+ /// instantiating and then re-canonicalizing the binder of the projection goal
297
+ /// forces us to be unable to see that the leak check failed in the nested
298
+ /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
299
+ /// that should catch when a projection goal fails due to an unsatisfied trait
300
+ /// goal.
301
+ fn detect_error_in_higher_ranked_projection (
302
+ & mut self ,
303
+ goal : & inspect:: InspectGoal < ' _ , ' tcx > ,
304
+ ) -> ControlFlow < PredicateObligation < ' tcx > > {
305
+ let tcx = goal. infcx ( ) . tcx ;
306
+ if let Some ( projection_clause) = goal. goal ( ) . predicate . as_projection_clause ( )
307
+ && !projection_clause. bound_vars ( ) . is_empty ( )
308
+ {
309
+ let pred = projection_clause. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ;
310
+ self . with_derived_obligation ( self . obligation . with ( tcx, pred) , |this| {
311
+ goal. infcx ( ) . visit_proof_tree_at_depth (
312
+ goal. goal ( ) . with ( tcx, pred) ,
313
+ goal. depth ( ) + 1 ,
314
+ this,
315
+ )
316
+ } )
317
+ } else {
318
+ ControlFlow :: Continue ( ( ) )
319
+ }
320
+ }
321
+
294
322
/// It is likely that `NormalizesTo` failed without any applicable candidates
295
323
/// because the alias is not well-formed.
296
324
///
@@ -374,7 +402,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
374
402
source : CandidateSource :: Impl ( impl_def_id) ,
375
403
result : _,
376
404
} = candidate. kind ( )
377
- && goal . infcx ( ) . tcx . do_not_recommend_impl ( impl_def_id)
405
+ && tcx. do_not_recommend_impl ( impl_def_id)
378
406
{
379
407
trace ! ( "#[do_not_recommend] -> exit" ) ;
380
408
return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
@@ -486,7 +514,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
486
514
if let Some ( obligation) = goal
487
515
. infcx ( )
488
516
. visit_proof_tree_at_depth (
489
- goal. goal ( ) . with ( goal . infcx ( ) . tcx , ty:: ClauseKind :: WellFormed ( lhs. into ( ) ) ) ,
517
+ goal. goal ( ) . with ( tcx, ty:: ClauseKind :: WellFormed ( lhs. into ( ) ) ) ,
490
518
goal. depth ( ) + 1 ,
491
519
self ,
492
520
)
@@ -496,7 +524,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
496
524
} else if let Some ( obligation) = goal
497
525
. infcx ( )
498
526
. visit_proof_tree_at_depth (
499
- goal. goal ( ) . with ( goal . infcx ( ) . tcx , ty:: ClauseKind :: WellFormed ( rhs. into ( ) ) ) ,
527
+ goal. goal ( ) . with ( tcx, ty:: ClauseKind :: WellFormed ( rhs. into ( ) ) ) ,
500
528
goal. depth ( ) + 1 ,
501
529
self ,
502
530
)
@@ -506,6 +534,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
506
534
}
507
535
}
508
536
537
+ self . detect_error_in_higher_ranked_projection ( goal) ?;
538
+
509
539
ControlFlow :: Break ( self . obligation . clone ( ) )
510
540
}
511
541
}
0 commit comments