@@ -11,8 +11,9 @@ use rustc_type_ir::lang_items::SolverTraitLangItem;
1111use  rustc_type_ir:: search_graph:: CandidateHeadUsages ; 
1212use  rustc_type_ir:: solve:: SizedTraitKind ; 
1313use  rustc_type_ir:: { 
14-     self  as  ty,  Interner ,  TypeFlags ,  TypeFoldable ,  TypeSuperVisitable ,  TypeVisitable , 
15-     TypeVisitableExt  as  _,  TypeVisitor ,  TypingMode ,  Upcast  as  _,  elaborate, 
14+     self  as  ty,  Interner ,  TypeFlags ,  TypeFoldable ,  TypeFolder ,  TypeSuperFoldable , 
15+     TypeSuperVisitable ,  TypeVisitable ,  TypeVisitableExt ,  TypeVisitor ,  TypingMode ,  Upcast , 
16+     elaborate, 
1617} ; 
1718use  tracing:: { debug,  instrument} ; 
1819
@@ -187,6 +188,7 @@ where
187188        ecx :  & mut  EvalCtxt < ' _ ,  D > , 
188189        goal :  Goal < I ,  Self > , 
189190        impl_def_id :  I :: ImplId , 
191+         then :  impl  FnOnce ( & mut  EvalCtxt < ' _ ,  D > ,  Certainty )  -> QueryResult < I > , 
190192    )  -> Result < Candidate < I > ,  NoSolution > ; 
191193
192194    /// If the predicate contained an error, we want to avoid emitting unnecessary trait 
@@ -365,6 +367,15 @@ pub(super) enum AssembleCandidatesFrom {
365367EnvAndBounds , 
366368} 
367369
370+ impl  AssembleCandidatesFrom  { 
371+     fn  should_assemble_impl_candidates ( & self )  -> bool  { 
372+         match  self  { 
373+             AssembleCandidatesFrom :: All  => true , 
374+             AssembleCandidatesFrom :: EnvAndBounds  => false , 
375+         } 
376+     } 
377+ } 
378+ 
368379/// This is currently used to track the [CandidateHeadUsages] of all failed `ParamEnv` 
369380/// candidates. This is then used to ignore their head usages in case there's another 
370381/// always applicable `ParamEnv` candidate. Look at how `param_env_head_usages` is 
@@ -397,14 +408,15 @@ where
397408            return  ( candidates,  failed_candidate_info) ; 
398409        } ; 
399410
411+         let  goal:  Goal < I ,  G >  = goal
412+             . with ( self . cx ( ) ,  goal. predicate . with_replaced_self_ty ( self . cx ( ) ,  normalized_self_ty) ) ; 
413+ 
400414        if  normalized_self_ty. is_ty_var ( )  { 
401415            debug ! ( "self type has been normalized to infer" ) ; 
402-             candidates . extend ( self . forced_ambiguity ( MaybeCause :: Ambiguity ) ) ; 
416+             self . try_assemble_bounds_via_registered_opaques ( goal ,  assemble_from ,   & mut  candidates ) ; 
403417            return  ( candidates,  failed_candidate_info) ; 
404418        } 
405419
406-         let  goal:  Goal < I ,  G >  = goal
407-             . with ( self . cx ( ) ,  goal. predicate . with_replaced_self_ty ( self . cx ( ) ,  normalized_self_ty) ) ; 
408420        // Vars that show up in the rest of the goal substs may have been constrained by 
409421        // normalizing the self type as well, since type variables are not uniquified. 
410422        let  goal = self . resolve_vars_if_possible ( goal) ; 
@@ -484,8 +496,9 @@ where
484496                if  cx. impl_is_default ( impl_def_id)  { 
485497                    return ; 
486498                } 
487- 
488-                 match  G :: consider_impl_candidate ( self ,  goal,  impl_def_id)  { 
499+                 match  G :: consider_impl_candidate ( self ,  goal,  impl_def_id,  |ecx,  certainty| { 
500+                     ecx. evaluate_added_goals_and_make_canonical_response ( certainty) 
501+                 } )  { 
489502                    Ok ( candidate)  => candidates. push ( candidate) , 
490503                    Err ( NoSolution )  => ( ) , 
491504                } 
@@ -943,6 +956,116 @@ where
943956        } 
944957    } 
945958
959+     /// If the self type is the hidden type of an opaque, try to assemble 
960+ /// candidates for it by consider its item bounds and by using blanket 
961+ /// impls. This is used to incompletely guide type inference when handling 
962+ /// non-defining uses in the defining scope. 
963+ /// 
964+ /// We otherwise just fail fail with ambiguity. Even if we're using an 
965+ /// opaque type item bound or a blank impls, we still force its certainty 
966+ /// to be `Maybe` so that we properly prove this goal later. 
967+ /// 
968+ /// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/182> 
969+ /// for why this is necessary. 
970+ fn  try_assemble_bounds_via_registered_opaques < G :  GoalKind < D > > ( 
971+         & mut  self , 
972+         goal :  Goal < I ,  G > , 
973+         assemble_from :  AssembleCandidatesFrom , 
974+         candidates :  & mut  Vec < Candidate < I > > , 
975+     )  { 
976+         let  self_ty = goal. predicate . self_ty ( ) ; 
977+         // If the self type is sub unified with any opaque type, we 
978+         // also look at blanket impls for it. 
979+         let  mut  assemble_blanket_impls = false ; 
980+         for  alias_ty in  self . opaques_with_sub_unified_hidden_type ( self_ty)  { 
981+             assemble_blanket_impls = true ; 
982+             debug ! ( "self ty is sub unified with {alias_ty:?}" ) ; 
983+ 
984+             struct  ReplaceOpaque < I :  Interner >  { 
985+                 cx :  I , 
986+                 alias_ty :  ty:: AliasTy < I > , 
987+                 self_ty :  I :: Ty , 
988+             } 
989+             impl < I :  Interner >  TypeFolder < I >  for  ReplaceOpaque < I >  { 
990+                 fn  cx ( & self )  -> I  { 
991+                     self . cx 
992+                 } 
993+                 fn  fold_ty ( & mut  self ,  ty :  I :: Ty )  -> I :: Ty  { 
994+                     if  let  ty:: Alias ( ty:: Opaque ,  alias_ty)  = ty. kind ( )  { 
995+                         if  alias_ty == self . alias_ty  { 
996+                             return  self . self_ty ; 
997+                         } 
998+                     } 
999+                     ty. super_fold_with ( self ) 
1000+                 } 
1001+             } 
1002+ 
1003+             // We look at all item-bounds of the opaque, replacing the 
1004+             // opaque with the current self type before considering 
1005+             // them as a candidate. Imagine e've got `?x: Trait<?y>` 
1006+             // and `?x` has been sub-unified with the hidden type of 
1007+             // `impl Trait<u32>`, We take the item bound `opaque: Trait<u32>` 
1008+             // and replace all occurrences of `opaque` with `?x`. This results 
1009+             // in a `?x: Trait<u32>` alias-bound candidate. 
1010+             for  item_bound in  self 
1011+                 . cx ( ) 
1012+                 . item_self_bounds ( alias_ty. def_id ) 
1013+                 . iter_instantiated ( self . cx ( ) ,  alias_ty. args ) 
1014+             { 
1015+                 let  assumption =
1016+                     item_bound. fold_with ( & mut  ReplaceOpaque  {  cx :  self . cx ( ) ,  alias_ty,  self_ty } ) ; 
1017+                 candidates. extend ( G :: probe_and_match_goal_against_assumption ( 
1018+                     self , 
1019+                     CandidateSource :: AliasBound , 
1020+                     goal, 
1021+                     assumption, 
1022+                     |ecx| { 
1023+                         // We want to reprove this goal once we've inferred the 
1024+                         // hidden type, so we force the certainty to `Maybe`. 
1025+                         ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS ) 
1026+                     } , 
1027+                 ) ) ; 
1028+             } 
1029+         } 
1030+ 
1031+         // We also need to consider blanket impls for not-yet-defined opaque types. 
1032+         // 
1033+         // See tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs for an example. 
1034+         if  assemble_blanket_impls && assemble_from. should_assemble_impl_candidates ( )  { 
1035+             let  cx = self . cx ( ) ; 
1036+             cx. for_each_blanket_impl ( goal. predicate . trait_def_id ( cx) ,  |impl_def_id| { 
1037+                 // For every `default impl`, there's always a non-default `impl` 
1038+                 // that will *also* apply. There's no reason to register a candidate 
1039+                 // for this impl, since it is *not* proof that the trait goal holds. 
1040+                 if  cx. impl_is_default ( impl_def_id)  { 
1041+                     return ; 
1042+                 } 
1043+ 
1044+                 match  G :: consider_impl_candidate ( self ,  goal,  impl_def_id,  |ecx,  certainty| { 
1045+                     if  ecx. shallow_resolve ( self_ty) . is_ty_var ( )  { 
1046+                         // We force the certainty of impl candidates to be `Maybe`. 
1047+                         let  certainty = certainty. and ( Certainty :: AMBIGUOUS ) ; 
1048+                         ecx. evaluate_added_goals_and_make_canonical_response ( certainty) 
1049+                     }  else  { 
1050+                         // We don't want to use impls if they constrain the opaque. 
1051+                         // 
1052+                         // FIXME(trait-system-refactor-initiative#229): This isn't 
1053+                         // perfect yet as it still allows us to incorrectly constrain 
1054+                         // other inference variables. 
1055+                         Err ( NoSolution ) 
1056+                     } 
1057+                 } )  { 
1058+                     Ok ( candidate)  => candidates. push ( candidate) , 
1059+                     Err ( NoSolution )  => ( ) , 
1060+                 } 
1061+             } ) ; 
1062+         } 
1063+ 
1064+         if  candidates. is_empty ( )  { 
1065+             candidates. extend ( self . forced_ambiguity ( MaybeCause :: Ambiguity ) ) ; 
1066+         } 
1067+     } 
1068+ 
9461069    /// Assemble and merge candidates for goals which are related to an underlying trait 
9471070/// goal. Right now, this is normalizes-to and host effect goals. 
9481071/// 
0 commit comments