1
1
//! Code shared by trait and projection goals for candidate assembly.
2
2
3
+ use derivative:: Derivative ;
3
4
use rustc_hir:: def_id:: DefId ;
4
5
use rustc_infer:: infer:: InferCtxt ;
5
6
use rustc_infer:: traits:: query:: NoSolution ;
6
7
use rustc_middle:: bug;
7
8
use rustc_middle:: traits:: solve:: inspect:: ProbeKind ;
8
- use rustc_middle:: traits:: solve:: {
9
- CandidateSource , CanonicalResponse , Certainty , Goal , MaybeCause , QueryResult ,
10
- } ;
9
+ use rustc_middle:: traits:: solve:: { Certainty , Goal , MaybeCause , QueryResult } ;
11
10
use rustc_middle:: traits:: BuiltinImplSource ;
12
11
use rustc_middle:: ty:: fast_reject:: { SimplifiedType , TreatParams } ;
13
12
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
14
13
use rustc_middle:: ty:: { fast_reject, TypeFoldable } ;
15
14
use rustc_middle:: ty:: { TypeVisitableExt , Upcast } ;
16
15
use rustc_span:: { ErrorGuaranteed , DUMMY_SP } ;
17
- use std:: fmt:: Debug ;
16
+ use rustc_type_ir:: solve:: { CandidateSource , CanonicalResponse } ;
17
+ use rustc_type_ir:: Interner ;
18
18
19
19
use crate :: solve:: GoalSource ;
20
20
use crate :: solve:: { EvalCtxt , SolverMode } ;
@@ -25,10 +25,11 @@ pub(super) mod structural_traits;
25
25
///
26
26
/// It consists of both the `source`, which describes how that goal would be proven,
27
27
/// and the `result` when using the given `source`.
28
- #[ derive( Debug , Clone ) ]
29
- pub ( super ) struct Candidate < ' tcx > {
30
- pub ( super ) source : CandidateSource < ' tcx > ,
31
- pub ( super ) result : CanonicalResponse < ' tcx > ,
28
+ #[ derive( Derivative ) ]
29
+ #[ derivative( Debug ( bound = "" ) , Clone ( bound = "" ) ) ]
30
+ pub ( super ) struct Candidate < I : Interner > {
31
+ pub ( super ) source : CandidateSource < I > ,
32
+ pub ( super ) result : CanonicalResponse < I > ,
32
33
}
33
34
34
35
/// Methods used to assemble candidates for either trait or projection goals.
@@ -49,22 +50,22 @@ pub(super) trait GoalKind<'tcx>:
49
50
/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
50
51
fn probe_and_match_goal_against_assumption (
51
52
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
52
- source : CandidateSource < ' tcx > ,
53
+ source : CandidateSource < TyCtxt < ' tcx > > ,
53
54
goal : Goal < ' tcx , Self > ,
54
55
assumption : ty:: Clause < ' tcx > ,
55
56
then : impl FnOnce ( & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ) -> QueryResult < ' tcx > ,
56
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
57
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
57
58
58
59
/// Consider a clause, which consists of a "assumption" and some "requirements",
59
60
/// to satisfy a goal. If the requirements hold, then attempt to satisfy our
60
61
/// goal by equating it with the assumption.
61
62
fn probe_and_consider_implied_clause (
62
63
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
63
- parent_source : CandidateSource < ' tcx > ,
64
+ parent_source : CandidateSource < TyCtxt < ' tcx > > ,
64
65
goal : Goal < ' tcx , Self > ,
65
66
assumption : ty:: Clause < ' tcx > ,
66
67
requirements : impl IntoIterator < Item = ( GoalSource , Goal < ' tcx , ty:: Predicate < ' tcx > > ) > ,
67
- ) -> Result < Candidate < ' tcx > , NoSolution > {
68
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > {
68
69
Self :: probe_and_match_goal_against_assumption ( ecx, parent_source, goal, assumption, |ecx| {
69
70
for ( nested_source, goal) in requirements {
70
71
ecx. add_goal ( nested_source, goal) ;
@@ -78,10 +79,10 @@ pub(super) trait GoalKind<'tcx>:
78
79
/// since they're not implied by the well-formedness of the object type.
79
80
fn probe_and_consider_object_bound_candidate (
80
81
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
81
- source : CandidateSource < ' tcx > ,
82
+ source : CandidateSource < TyCtxt < ' tcx > > ,
82
83
goal : Goal < ' tcx , Self > ,
83
84
assumption : ty:: Clause < ' tcx > ,
84
- ) -> Result < Candidate < ' tcx > , NoSolution > {
85
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > {
85
86
Self :: probe_and_match_goal_against_assumption ( ecx, source, goal, assumption, |ecx| {
86
87
let tcx = ecx. interner ( ) ;
87
88
let ty:: Dynamic ( bounds, _, _) = * goal. predicate . self_ty ( ) . kind ( ) else {
@@ -104,7 +105,7 @@ pub(super) trait GoalKind<'tcx>:
104
105
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
105
106
goal : Goal < ' tcx , Self > ,
106
107
impl_def_id : DefId ,
107
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
108
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
108
109
109
110
/// If the predicate contained an error, we want to avoid emitting unnecessary trait
110
111
/// errors but still want to emit errors for other trait goals. We have some special
@@ -115,7 +116,7 @@ pub(super) trait GoalKind<'tcx>:
115
116
fn consider_error_guaranteed_candidate (
116
117
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
117
118
guar : ErrorGuaranteed ,
118
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
119
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
119
120
120
121
/// A type implements an `auto trait` if its components do as well.
121
122
///
@@ -124,13 +125,13 @@ pub(super) trait GoalKind<'tcx>:
124
125
fn consider_auto_trait_candidate (
125
126
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
126
127
goal : Goal < ' tcx , Self > ,
127
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
128
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
128
129
129
130
/// A trait alias holds if the RHS traits and `where` clauses hold.
130
131
fn consider_trait_alias_candidate (
131
132
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
132
133
goal : Goal < ' tcx , Self > ,
133
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
134
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
134
135
135
136
/// A type is `Sized` if its tail component is `Sized`.
136
137
///
@@ -139,7 +140,7 @@ pub(super) trait GoalKind<'tcx>:
139
140
fn consider_builtin_sized_candidate (
140
141
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
141
142
goal : Goal < ' tcx , Self > ,
142
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
143
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
143
144
144
145
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
145
146
///
@@ -148,50 +149,50 @@ pub(super) trait GoalKind<'tcx>:
148
149
fn consider_builtin_copy_clone_candidate (
149
150
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
150
151
goal : Goal < ' tcx , Self > ,
151
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
152
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
152
153
153
154
/// A type is `PointerLike` if we can compute its layout, and that layout
154
155
/// matches the layout of `usize`.
155
156
fn consider_builtin_pointer_like_candidate (
156
157
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
157
158
goal : Goal < ' tcx , Self > ,
158
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
159
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
159
160
160
161
/// A type is a `FnPtr` if it is of `FnPtr` type.
161
162
fn consider_builtin_fn_ptr_trait_candidate (
162
163
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
163
164
goal : Goal < ' tcx , Self > ,
164
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
165
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
165
166
166
167
/// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
167
168
/// family of traits where `A` is given by the signature of the type.
168
169
fn consider_builtin_fn_trait_candidates (
169
170
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
170
171
goal : Goal < ' tcx , Self > ,
171
172
kind : ty:: ClosureKind ,
172
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
173
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
173
174
174
175
/// An async closure is known to implement the `AsyncFn<A>` family of traits
175
176
/// where `A` is given by the signature of the type.
176
177
fn consider_builtin_async_fn_trait_candidates (
177
178
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
178
179
goal : Goal < ' tcx , Self > ,
179
180
kind : ty:: ClosureKind ,
180
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
181
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
181
182
182
183
/// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
183
184
/// is used internally to delay computation for async closures until after
184
185
/// upvar analysis is performed in HIR typeck.
185
186
fn consider_builtin_async_fn_kind_helper_candidate (
186
187
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
187
188
goal : Goal < ' tcx , Self > ,
188
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
189
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
189
190
190
191
/// `Tuple` is implemented if the `Self` type is a tuple.
191
192
fn consider_builtin_tuple_candidate (
192
193
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
193
194
goal : Goal < ' tcx , Self > ,
194
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
195
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
195
196
196
197
/// `Pointee` is always implemented.
197
198
///
@@ -201,63 +202,63 @@ pub(super) trait GoalKind<'tcx>:
201
202
fn consider_builtin_pointee_candidate (
202
203
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
203
204
goal : Goal < ' tcx , Self > ,
204
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
205
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
205
206
206
207
/// A coroutine (that comes from an `async` desugaring) is known to implement
207
208
/// `Future<Output = O>`, where `O` is given by the coroutine's return type
208
209
/// that was computed during type-checking.
209
210
fn consider_builtin_future_candidate (
210
211
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
211
212
goal : Goal < ' tcx , Self > ,
212
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
213
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
213
214
214
215
/// A coroutine (that comes from a `gen` desugaring) is known to implement
215
216
/// `Iterator<Item = O>`, where `O` is given by the generator's yield type
216
217
/// that was computed during type-checking.
217
218
fn consider_builtin_iterator_candidate (
218
219
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
219
220
goal : Goal < ' tcx , Self > ,
220
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
221
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
221
222
222
223
/// A coroutine (that comes from a `gen` desugaring) is known to implement
223
224
/// `FusedIterator`
224
225
fn consider_builtin_fused_iterator_candidate (
225
226
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
226
227
goal : Goal < ' tcx , Self > ,
227
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
228
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
228
229
229
230
fn consider_builtin_async_iterator_candidate (
230
231
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
231
232
goal : Goal < ' tcx , Self > ,
232
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
233
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
233
234
234
235
/// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
235
236
/// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
236
237
/// and return types of the coroutine computed during type-checking.
237
238
fn consider_builtin_coroutine_candidate (
238
239
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
239
240
goal : Goal < ' tcx , Self > ,
240
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
241
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
241
242
242
243
fn consider_builtin_discriminant_kind_candidate (
243
244
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
244
245
goal : Goal < ' tcx , Self > ,
245
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
246
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
246
247
247
248
fn consider_builtin_async_destruct_candidate (
248
249
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
249
250
goal : Goal < ' tcx , Self > ,
250
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
251
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
251
252
252
253
fn consider_builtin_destruct_candidate (
253
254
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
254
255
goal : Goal < ' tcx , Self > ,
255
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
256
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
256
257
257
258
fn consider_builtin_transmute_candidate (
258
259
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
259
260
goal : Goal < ' tcx , Self > ,
260
- ) -> Result < Candidate < ' tcx > , NoSolution > ;
261
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > ;
261
262
262
263
/// Consider (possibly several) candidates to upcast or unsize a type to another
263
264
/// type, excluding the coercion of a sized type into a `dyn Trait`.
@@ -269,14 +270,14 @@ pub(super) trait GoalKind<'tcx>:
269
270
fn consider_structural_builtin_unsize_candidates (
270
271
ecx : & mut EvalCtxt < ' _ , InferCtxt < ' tcx > > ,
271
272
goal : Goal < ' tcx , Self > ,
272
- ) -> Vec < Candidate < ' tcx > > ;
273
+ ) -> Vec < Candidate < TyCtxt < ' tcx > > > ;
273
274
}
274
275
275
276
impl < ' tcx > EvalCtxt < ' _ , InferCtxt < ' tcx > > {
276
277
pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < ' tcx > > (
277
278
& mut self ,
278
279
goal : Goal < ' tcx , G > ,
279
- ) -> Vec < Candidate < ' tcx > > {
280
+ ) -> Vec < Candidate < TyCtxt < ' tcx > > > {
280
281
let Ok ( normalized_self_ty) =
281
282
self . structurally_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
282
283
else {
@@ -323,7 +324,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
323
324
pub ( super ) fn forced_ambiguity (
324
325
& mut self ,
325
326
cause : MaybeCause ,
326
- ) -> Result < Candidate < ' tcx > , NoSolution > {
327
+ ) -> Result < Candidate < TyCtxt < ' tcx > > , NoSolution > {
327
328
// This may fail if `try_evaluate_added_goals` overflows because it
328
329
// fails to reach a fixpoint but ends up getting an error after
329
330
// running for some additional step.
@@ -339,7 +340,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
339
340
fn assemble_non_blanket_impl_candidates < G : GoalKind < ' tcx > > (
340
341
& mut self ,
341
342
goal : Goal < ' tcx , G > ,
342
- candidates : & mut Vec < Candidate < ' tcx > > ,
343
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
343
344
) {
344
345
let tcx = self . interner ( ) ;
345
346
let self_ty = goal. predicate . self_ty ( ) ;
@@ -455,7 +456,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
455
456
fn assemble_blanket_impl_candidates < G : GoalKind < ' tcx > > (
456
457
& mut self ,
457
458
goal : Goal < ' tcx , G > ,
458
- candidates : & mut Vec < Candidate < ' tcx > > ,
459
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
459
460
) {
460
461
let tcx = self . interner ( ) ;
461
462
let trait_impls = tcx. trait_impls_of ( goal. predicate . trait_def_id ( tcx) ) ;
@@ -478,7 +479,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
478
479
fn assemble_builtin_impl_candidates < G : GoalKind < ' tcx > > (
479
480
& mut self ,
480
481
goal : Goal < ' tcx , G > ,
481
- candidates : & mut Vec < Candidate < ' tcx > > ,
482
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
482
483
) {
483
484
let tcx = self . interner ( ) ;
484
485
let lang_items = tcx. lang_items ( ) ;
@@ -552,7 +553,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
552
553
fn assemble_param_env_candidates < G : GoalKind < ' tcx > > (
553
554
& mut self ,
554
555
goal : Goal < ' tcx , G > ,
555
- candidates : & mut Vec < Candidate < ' tcx > > ,
556
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
556
557
) {
557
558
for ( i, assumption) in goal. param_env . caller_bounds ( ) . iter ( ) . enumerate ( ) {
558
559
candidates. extend ( G :: probe_and_consider_implied_clause (
@@ -569,7 +570,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
569
570
fn assemble_alias_bound_candidates < G : GoalKind < ' tcx > > (
570
571
& mut self ,
571
572
goal : Goal < ' tcx , G > ,
572
- candidates : & mut Vec < Candidate < ' tcx > > ,
573
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
573
574
) {
574
575
let ( ) = self . probe ( |_| ProbeKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
575
576
ecx. assemble_alias_bound_candidates_recur ( goal. predicate . self_ty ( ) , goal, candidates) ;
@@ -589,7 +590,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
589
590
& mut self ,
590
591
self_ty : Ty < ' tcx > ,
591
592
goal : Goal < ' tcx , G > ,
592
- candidates : & mut Vec < Candidate < ' tcx > > ,
593
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
593
594
) {
594
595
let ( kind, alias_ty) = match * self_ty. kind ( ) {
595
596
ty:: Bool
@@ -673,7 +674,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
673
674
fn assemble_object_bound_candidates < G : GoalKind < ' tcx > > (
674
675
& mut self ,
675
676
goal : Goal < ' tcx , G > ,
676
- candidates : & mut Vec < Candidate < ' tcx > > ,
677
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
677
678
) {
678
679
let tcx = self . interner ( ) ;
679
680
if !tcx. trait_def ( goal. predicate . trait_def_id ( tcx) ) . implement_via_object {
@@ -764,7 +765,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
764
765
fn assemble_coherence_unknowable_candidates < G : GoalKind < ' tcx > > (
765
766
& mut self ,
766
767
goal : Goal < ' tcx , G > ,
767
- candidates : & mut Vec < Candidate < ' tcx > > ,
768
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
768
769
) {
769
770
let tcx = self . interner ( ) ;
770
771
@@ -793,7 +794,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
793
794
fn discard_impls_shadowed_by_env < G : GoalKind < ' tcx > > (
794
795
& mut self ,
795
796
goal : Goal < ' tcx , G > ,
796
- candidates : & mut Vec < Candidate < ' tcx > > ,
797
+ candidates : & mut Vec < Candidate < TyCtxt < ' tcx > > > ,
797
798
) {
798
799
let tcx = self . interner ( ) ;
799
800
let trait_goal: Goal < ' tcx , ty:: TraitPredicate < ' tcx > > =
@@ -841,7 +842,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
841
842
#[ instrument( level = "debug" , skip( self ) , ret) ]
842
843
pub ( super ) fn merge_candidates (
843
844
& mut self ,
844
- candidates : Vec < Candidate < ' tcx > > ,
845
+ candidates : Vec < Candidate < TyCtxt < ' tcx > > > ,
845
846
) -> QueryResult < ' tcx > {
846
847
// First try merging all candidates. This is complete and fully sound.
847
848
let responses = candidates. iter ( ) . map ( |c| c. result ) . collect :: < Vec < _ > > ( ) ;
0 commit comments