2
2
3
3
pub ( super ) mod structural_traits;
4
4
5
+ use std:: cell:: Cell ;
5
6
use std:: ops:: ControlFlow ;
6
7
7
8
use derive_where:: derive_where;
@@ -117,24 +118,24 @@ where
117
118
) -> Result < Candidate < I > , NoSolution > {
118
119
Self :: fast_reject_assumption ( ecx, goal, assumption) ?;
119
120
120
- ecx. probe ( |candidate : & Result < Candidate < I > , NoSolution > | match candidate {
121
- Ok ( candidate) => inspect:: ProbeKind :: TraitCandidate {
122
- source : candidate. source ,
123
- result : Ok ( candidate. result ) ,
124
- } ,
125
- Err ( NoSolution ) => inspect:: ProbeKind :: TraitCandidate {
126
- source : CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ,
127
- result : Err ( NoSolution ) ,
128
- } ,
121
+ // Dealing with `ParamEnv` candidates is a bit of a mess as we need to lazily
122
+ // check whether the candidate is global while considering normalization.
123
+ //
124
+ // We need to write into `source` inside of `match_assumption`, but need to access it
125
+ // in `probe` even if the candidate does not apply before we get there. We handle this
126
+ // by using a `Cell` here. We only ever write into it inside of `match_assumption`.
127
+ let source = Cell :: new ( CandidateSource :: ParamEnv ( ParamEnvSource :: Global ) ) ;
128
+ ecx. probe ( |result : & QueryResult < I > | inspect:: ProbeKind :: TraitCandidate {
129
+ source : source. get ( ) ,
130
+ result : * result,
129
131
} )
130
132
. enter ( |ecx| {
131
- Self :: match_assumption ( ecx, goal, assumption) ?;
132
- let source = ecx. characterize_param_env_assumption ( goal. param_env , assumption) ?;
133
- Ok ( Candidate {
134
- source,
135
- result : ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ?,
133
+ Self :: match_assumption ( ecx, goal, assumption, |ecx| {
134
+ source. set ( ecx. characterize_param_env_assumption ( goal. param_env , assumption) ?) ;
135
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
136
136
} )
137
137
} )
138
+ . map ( |result| Candidate { source : source. get ( ) , result } )
138
139
}
139
140
140
141
/// Try equating an assumption predicate against a goal's predicate. If it
@@ -150,10 +151,8 @@ where
150
151
) -> Result < Candidate < I > , NoSolution > {
151
152
Self :: fast_reject_assumption ( ecx, goal, assumption) ?;
152
153
153
- ecx. probe_trait_candidate ( source) . enter ( |ecx| {
154
- Self :: match_assumption ( ecx, goal, assumption) ?;
155
- then ( ecx)
156
- } )
154
+ ecx. probe_trait_candidate ( source)
155
+ . enter ( |ecx| Self :: match_assumption ( ecx, goal, assumption, then) )
157
156
}
158
157
159
158
/// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`]
@@ -169,7 +168,8 @@ where
169
168
ecx : & mut EvalCtxt < ' _ , D > ,
170
169
goal : Goal < I , Self > ,
171
170
assumption : I :: Clause ,
172
- ) -> Result < ( ) , NoSolution > ;
171
+ then : impl FnOnce ( & mut EvalCtxt < ' _ , D > ) -> QueryResult < I > ,
172
+ ) -> QueryResult < I > ;
173
173
174
174
fn consider_impl_candidate (
175
175
ecx : & mut EvalCtxt < ' _ , D > ,
0 commit comments