22
33pub ( super )  mod  structural_traits; 
44
5+ use  std:: ops:: ControlFlow ; 
6+ 
57use  derive_where:: derive_where; 
68use  rustc_type_ir:: inherent:: * ; 
79use  rustc_type_ir:: lang_items:: TraitSolverLangItem ; 
810use  rustc_type_ir:: { 
9-     self  as  ty,  Interner ,  TypeFoldable ,  TypeVisitableExt  as  _,  TypingMode ,  Upcast  as  _,  elaborate, 
11+     self  as  ty,  Interner ,  TypeFoldable ,  TypeSuperVisitable ,  TypeVisitable ,  TypeVisitableExt  as  _, 
12+     TypeVisitor ,  TypingMode ,  Upcast  as  _,  elaborate, 
1013} ; 
1114use  tracing:: { debug,  instrument} ; 
1215
16+ use  super :: inspect; 
1317use  super :: trait_goals:: TraitGoalProvenVia ; 
1418use  crate :: delegate:: SolverDelegate ; 
19+ use  crate :: resolve:: EagerResolver ; 
1520use  crate :: solve:: inspect:: ProbeKind ; 
1621use  crate :: solve:: { 
1722    BuiltinImplSource ,  CandidateSource ,  CanonicalResponse ,  Certainty ,  EvalCtxt ,  Goal ,  GoalSource , 
@@ -118,6 +123,38 @@ where
118123        alias_ty :  ty:: AliasTy < I > , 
119124    )  -> Vec < Candidate < I > > ; 
120125
126+     fn  probe_and_consider_param_env_candidate ( 
127+         ecx :  & mut  EvalCtxt < ' _ ,  D > , 
128+         goal :  Goal < I ,  Self > , 
129+         assumption :  I :: Clause , 
130+         idx :  usize , 
131+     )  -> Result < Candidate < I > ,  NoSolution >  { 
132+         ecx. probe ( |candidate :  & Result < Candidate < I > ,  NoSolution > | match  candidate { 
133+             Ok ( candidate)  => inspect:: ProbeKind :: TraitCandidate  { 
134+                 source :  candidate. source , 
135+                 result :  Ok ( candidate. result ) , 
136+             } , 
137+             Err ( NoSolution )  => inspect:: ProbeKind :: TraitCandidate  { 
138+                 source :  CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) , 
139+                 result :  Err ( NoSolution ) , 
140+             } , 
141+         } ) 
142+         . enter ( |ecx| { 
143+             Self :: match_param_env_candidate ( ecx,  goal,  assumption) ?; 
144+             let  source = ecx. characterize ( goal. param_env ,  assumption,  idx) ?; 
145+             Ok ( Candidate  { 
146+                 source, 
147+                 result :  ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ?, 
148+             } ) 
149+         } ) 
150+     } 
151+ 
152+     fn  match_param_env_candidate ( 
153+         ecx :  & mut  EvalCtxt < ' _ ,  D > , 
154+         goal :  Goal < I ,  Self > , 
155+         assumption :  I :: Clause , 
156+     )  -> Result < ( ) ,  NoSolution > ; 
157+ 
121158    fn  consider_impl_candidate ( 
122159        ecx :  & mut  EvalCtxt < ' _ ,  D > , 
123160        goal :  Goal < I ,  Self > , 
@@ -508,13 +545,7 @@ where
508545        candidates :  & mut  Vec < Candidate < I > > , 
509546    )  { 
510547        for  ( i,  assumption)  in  goal. param_env . caller_bounds ( ) . iter ( ) . enumerate ( )  { 
511-             candidates. extend ( G :: probe_and_consider_implied_clause ( 
512-                 self , 
513-                 CandidateSource :: ParamEnv ( i) , 
514-                 goal, 
515-                 assumption, 
516-                 [ ] , 
517-             ) ) ; 
548+             candidates. extend ( G :: probe_and_consider_param_env_candidate ( self ,  goal,  assumption,  i) ) ; 
518549        } 
519550    } 
520551
@@ -831,11 +862,20 @@ where
831862                // See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`. 
832863                let  mut  considered_candidates:  Vec < _ >  = if  candidates_from_env_and_bounds
833864                    . iter ( ) 
834-                     . any ( |c| matches ! ( c. source,  CandidateSource :: ParamEnv ( _) ) ) 
835-                 { 
865+                     . any ( |c| { 
866+                         matches ! ( 
867+                             c. source, 
868+                             CandidateSource :: ParamEnv ( _)  | CandidateSource :: GlobalParamEnv ( _) 
869+                         ) 
870+                     } )  { 
836871                    candidates_from_env_and_bounds
837872                        . into_iter ( ) 
838-                         . filter ( |c| matches ! ( c. source,  CandidateSource :: ParamEnv ( _) ) ) 
873+                         . filter ( |c| { 
874+                             matches ! ( 
875+                                 c. source, 
876+                                 CandidateSource :: ParamEnv ( _)  | CandidateSource :: GlobalParamEnv ( _) 
877+                             ) 
878+                         } ) 
839879                        . map ( |c| c. result ) 
840880                        . collect ( ) 
841881                }  else  { 
@@ -864,7 +904,12 @@ where
864904                // (for example, and ideally only) when proving item bounds for an impl. 
865905                let  candidates_from_env:  Vec < _ >  = candidates
866906                    . iter ( ) 
867-                     . filter ( |c| matches ! ( c. source,  CandidateSource :: ParamEnv ( _) ) ) 
907+                     . filter ( |c| { 
908+                         matches ! ( 
909+                             c. source, 
910+                             CandidateSource :: ParamEnv ( _)  | CandidateSource :: GlobalParamEnv ( _) 
911+                         ) 
912+                     } ) 
868913                    . map ( |c| c. result ) 
869914                    . collect ( ) ; 
870915                if  let  Some ( response)  = self . try_merge_responses ( & candidates_from_env)  { 
@@ -880,4 +925,77 @@ where
880925            } 
881926        } 
882927    } 
928+ 
929+     fn  characterize ( 
930+         & mut  self , 
931+         param_env :  I :: ParamEnv , 
932+         assumption :  I :: Clause , 
933+         idx :  usize , 
934+     )  -> Result < CandidateSource < I > ,  NoSolution >  { 
935+         // FIXME: 
936+         if  assumption. has_bound_vars ( )  { 
937+             return  Ok ( CandidateSource :: ParamEnv ( idx) ) ; 
938+         } 
939+ 
940+         match  assumption. visit_with ( & mut  FindParamInClause  {  ecx :  self ,  param_env } )  { 
941+             ControlFlow :: Break ( Err ( NoSolution ) )  => Err ( NoSolution ) , 
942+             ControlFlow :: Break ( Ok ( ( ) ) )  => Ok ( CandidateSource :: ParamEnv ( idx) ) , 
943+             ControlFlow :: Continue ( ( ) )  => Ok ( CandidateSource :: GlobalParamEnv ( idx) ) , 
944+         } 
945+     } 
946+ } 
947+ 
948+ struct  FindParamInClause < ' a ,  ' b ,  D :  SolverDelegate < Interner  = I > ,  I :  Interner >  { 
949+     ecx :  & ' a  mut  EvalCtxt < ' b ,  D > , 
950+     param_env :  I :: ParamEnv , 
951+ } 
952+ 
953+ impl < D ,  I >  TypeVisitor < I >  for  FindParamInClause < ' _ ,  ' _ ,  D ,  I > 
954+ where 
955+     D :  SolverDelegate < Interner  = I > , 
956+     I :  Interner , 
957+ { 
958+     type  Result  = ControlFlow < Result < ( ) ,  NoSolution > > ; 
959+ 
960+     fn  visit_binder < T :  TypeFoldable < I > > ( & mut  self ,  t :  & ty:: Binder < I ,  T > )  -> Self :: Result  { 
961+         self . ecx . enter_forall ( t. clone ( ) ,  |ecx,  v| { 
962+             v. visit_with ( & mut  FindParamInClause  {  ecx,  param_env :  self . param_env  } ) 
963+         } ) 
964+     } 
965+ 
966+     fn  visit_ty ( & mut  self ,  ty :  I :: Ty )  -> Self :: Result  { 
967+         let  Ok ( ty)  = self . ecx . structurally_normalize_ty ( self . param_env ,  ty)  else  { 
968+             return  ControlFlow :: Break ( Err ( NoSolution ) ) ; 
969+         } ; 
970+         let  ty = ty. fold_with ( & mut  EagerResolver :: new ( self . ecx . delegate ) ) ; 
971+ 
972+         if  let  ty:: Placeholder ( _)  = ty. kind ( )  { 
973+             ControlFlow :: Break ( Ok ( ( ) ) ) 
974+         }  else  { 
975+             ty. super_visit_with ( self ) 
976+         } 
977+     } 
978+ 
979+     fn  visit_const ( & mut  self ,  ct :  I :: Const )  -> Self :: Result  { 
980+         let  Ok ( ct)  = self . ecx . structurally_normalize_const ( self . param_env ,  ct)  else  { 
981+             return  ControlFlow :: Break ( Err ( NoSolution ) ) ; 
982+         } ; 
983+         let  ct = ct. fold_with ( & mut  EagerResolver :: new ( self . ecx . delegate ) ) ; 
984+ 
985+         if  let  ty:: ConstKind :: Placeholder ( _)  = ct. kind ( )  { 
986+             ControlFlow :: Break ( Ok ( ( ) ) ) 
987+         }  else  { 
988+             ct. super_visit_with ( self ) 
989+         } 
990+     } 
991+ 
992+     fn  visit_region ( & mut  self ,  r :  I :: Region )  -> Self :: Result  { 
993+         match  r. kind ( )  { 
994+             ty:: ReStatic  | ty:: ReError ( _)  => ControlFlow :: Continue ( ( ) ) , 
995+             ty:: ReVar ( _)  | ty:: RePlaceholder ( _)  => ControlFlow :: Break ( Ok ( ( ) ) ) , 
996+             ty:: ReErased  | ty:: ReEarlyParam ( _)  | ty:: ReLateParam ( _)  | ty:: ReBound ( ..)  => { 
997+                 unreachable ! ( ) 
998+             } 
999+         } 
1000+     } 
8831001} 
0 commit comments