@@ -291,6 +291,34 @@ impl<'tcx> BestObligation<'tcx> {
291291 }
292292 }
293293
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+
294322 /// It is likely that `NormalizesTo` failed without any applicable candidates
295323 /// because the alias is not well-formed.
296324 ///
@@ -374,7 +402,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
374402 source : CandidateSource :: Impl ( impl_def_id) ,
375403 result : _,
376404 } = candidate. kind ( )
377- && goal . infcx ( ) . tcx . do_not_recommend_impl ( impl_def_id)
405+ && tcx. do_not_recommend_impl ( impl_def_id)
378406 {
379407 trace ! ( "#[do_not_recommend] -> exit" ) ;
380408 return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
@@ -486,7 +514,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
486514 if let Some ( obligation) = goal
487515 . infcx ( )
488516 . 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 ( ) ) ) ,
490518 goal. depth ( ) + 1 ,
491519 self ,
492520 )
@@ -496,7 +524,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
496524 } else if let Some ( obligation) = goal
497525 . infcx ( )
498526 . 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 ( ) ) ) ,
500528 goal. depth ( ) + 1 ,
501529 self ,
502530 )
@@ -506,6 +534,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
506534 }
507535 }
508536
537+ self . detect_error_in_higher_ranked_projection ( goal) ?;
538+
509539 ControlFlow :: Break ( self . obligation . clone ( ) )
510540 }
511541}
0 commit comments