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