2
2
3
3
pub ( super ) mod structural_traits;
4
4
5
+ use std:: ops:: ControlFlow ;
6
+
5
7
use derive_where:: derive_where;
6
8
use rustc_type_ir:: inherent:: * ;
7
9
use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
8
10
use 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,
10
13
} ;
11
14
use tracing:: { debug, instrument} ;
12
15
16
+ use super :: inspect;
13
17
use super :: trait_goals:: TraitGoalProvenVia ;
14
18
use crate :: delegate:: SolverDelegate ;
19
+ use crate :: resolve:: EagerResolver ;
15
20
use crate :: solve:: inspect:: ProbeKind ;
16
21
use crate :: solve:: {
17
22
BuiltinImplSource , CandidateSource , CanonicalResponse , Certainty , EvalCtxt , Goal , GoalSource ,
@@ -118,6 +123,38 @@ where
118
123
alias_ty : ty:: AliasTy < I > ,
119
124
) -> Vec < Candidate < I > > ;
120
125
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
+
121
158
fn consider_impl_candidate (
122
159
ecx : & mut EvalCtxt < ' _ , D > ,
123
160
goal : Goal < I , Self > ,
@@ -508,13 +545,7 @@ where
508
545
candidates : & mut Vec < Candidate < I > > ,
509
546
) {
510
547
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) ) ;
518
549
}
519
550
}
520
551
@@ -831,11 +862,20 @@ where
831
862
// See `tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs`.
832
863
let mut considered_candidates: Vec < _ > = if candidates_from_env_and_bounds
833
864
. 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
+ } ) {
836
871
candidates_from_env_and_bounds
837
872
. 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
+ } )
839
879
. map ( |c| c. result )
840
880
. collect ( )
841
881
} else {
@@ -864,7 +904,12 @@ where
864
904
// (for example, and ideally only) when proving item bounds for an impl.
865
905
let candidates_from_env: Vec < _ > = candidates
866
906
. iter ( )
867
- . filter ( |c| matches ! ( c. source, CandidateSource :: ParamEnv ( _) ) )
907
+ . filter ( |c| {
908
+ matches ! (
909
+ c. source,
910
+ CandidateSource :: ParamEnv ( _) | CandidateSource :: GlobalParamEnv ( _)
911
+ )
912
+ } )
868
913
. map ( |c| c. result )
869
914
. collect ( ) ;
870
915
if let Some ( response) = self . try_merge_responses ( & candidates_from_env) {
@@ -880,4 +925,77 @@ where
880
925
}
881
926
}
882
927
}
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
+ }
883
1001
}
0 commit comments