@@ -290,6 +290,59 @@ impl<'tcx> BestObligation<'tcx> {
290290 ControlFlow :: Continue ( ( ) )
291291 }
292292 }
293+
294+ /// It is likely that `NormalizesTo` failed without any applicable candidates
295+ /// because the alias is not well-formed.
296+ ///
297+ /// As we only enter `RigidAlias` candidates if the trait bound of the associated type
298+ /// holds, we discard these candidates in `non_trivial_candidates` and always manually
299+ /// check this here.
300+ fn detect_non_well_formed_assoc_item (
301+ & mut self ,
302+ goal : & inspect:: InspectGoal < ' _ , ' tcx > ,
303+ alias : ty:: AliasTerm < ' tcx > ,
304+ ) -> ControlFlow < PredicateObligation < ' tcx > > {
305+ let tcx = goal. infcx ( ) . tcx ;
306+ let obligation = Obligation :: new (
307+ tcx,
308+ self . obligation . cause . clone ( ) ,
309+ goal. goal ( ) . param_env ,
310+ alias. trait_ref ( tcx) ,
311+ ) ;
312+ self . with_derived_obligation ( obligation, |this| {
313+ goal. infcx ( ) . visit_proof_tree_at_depth (
314+ goal. goal ( ) . with ( tcx, alias. trait_ref ( tcx) ) ,
315+ goal. depth ( ) + 1 ,
316+ this,
317+ )
318+ } )
319+ }
320+
321+ /// If we have no candidates, then it's likely that we a non-well-formed alias
322+ /// in the goal.
323+ fn detect_error_from_empty_candidates (
324+ & mut self ,
325+ goal : & inspect:: InspectGoal < ' _ , ' tcx > ,
326+ ) -> ControlFlow < PredicateObligation < ' tcx > > {
327+ let tcx = goal. infcx ( ) . tcx ;
328+ let pred_kind = goal. goal ( ) . predicate . kind ( ) ;
329+
330+ match pred_kind. no_bound_vars ( ) {
331+ Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) ) => {
332+ self . detect_error_in_self_ty_normalization ( goal, pred. self_ty ( ) ) ?;
333+ }
334+ Some ( ty:: PredicateKind :: NormalizesTo ( pred) )
335+ if let ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst =
336+ pred. alias . kind ( tcx) =>
337+ {
338+ self . detect_error_in_self_ty_normalization ( goal, pred. alias . self_ty ( ) ) ?;
339+ self . detect_non_well_formed_assoc_item ( goal, pred. alias ) ?;
340+ }
341+ Some ( _) | None => { }
342+ }
343+
344+ ControlFlow :: Break ( self . obligation . clone ( ) )
345+ }
293346}
294347
295348impl < ' tcx > ProofTreeVisitor < ' tcx > for BestObligation < ' tcx > {
@@ -311,40 +364,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
311364
312365 let candidates = self . non_trivial_candidates ( goal) ;
313366 let candidate = match candidates. as_slice ( ) {
314- [ ] => {
315- match pred_kind. no_bound_vars ( ) {
316- Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) ) => {
317- self . detect_error_in_self_ty_normalization ( goal, pred. self_ty ( ) ) ?;
318- }
319- Some ( ty:: PredicateKind :: NormalizesTo ( pred) )
320- if let ty:: AliasTermKind :: ProjectionTy
321- | ty:: AliasTermKind :: ProjectionConst = pred. alias . kind ( tcx) =>
322- {
323- self . detect_error_in_self_ty_normalization ( goal, pred. alias . self_ty ( ) ) ?;
324- // It is likely that `NormalizesTo` failed because the alias is not well-formed.
325- // As we only enter `RigidAlias` candidates if the trait bound of the associated type
326- // holds, we discard these candidates in `non_trivial_candidates` and always manually
327- // check this here.
328- let obligation = Obligation :: new (
329- tcx,
330- self . obligation . cause . clone ( ) ,
331- goal. goal ( ) . param_env ,
332- pred. alias . trait_ref ( tcx) ,
333- ) ;
334- self . with_derived_obligation ( obligation, |this| {
335- goal. infcx ( ) . visit_proof_tree_at_depth (
336- goal. goal ( ) . with ( tcx, pred. alias . trait_ref ( tcx) ) ,
337- goal. depth ( ) + 1 ,
338- this,
339- )
340- } ) ?;
341- }
342- Some ( _) | None => { }
343- }
344-
345- return ControlFlow :: Break ( self . obligation . clone ( ) ) ;
346- }
347367 [ candidate] => candidate,
368+ [ ] => return self . detect_error_from_empty_candidates ( goal) ,
348369 _ => return ControlFlow :: Break ( self . obligation . clone ( ) ) ,
349370 } ;
350371
0 commit comments