1
1
//! Code shared by trait and projection goals for candidate assembly.
2
2
3
3
use super :: infcx_ext:: InferCtxtExt ;
4
- use super :: { CanonicalResponse , Certainty , EvalCtxt , Goal } ;
4
+ use super :: { CanonicalResponse , EvalCtxt , Goal , QueryResult } ;
5
5
use rustc_hir:: def_id:: DefId ;
6
6
use rustc_infer:: traits:: query:: NoSolution ;
7
+ use rustc_infer:: traits:: util:: elaborate_predicates;
7
8
use rustc_middle:: ty:: TypeFoldable ;
8
9
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
9
10
use std:: fmt:: Debug ;
@@ -89,19 +90,35 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
89
90
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
90
91
goal : Goal < ' tcx , Self > ,
91
92
impl_def_id : DefId ,
92
- ) -> Result < Certainty , NoSolution > ;
93
+ ) -> QueryResult < ' tcx > ;
94
+
95
+ fn consider_assumption (
96
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
97
+ goal : Goal < ' tcx , Self > ,
98
+ assumption : ty:: Predicate < ' tcx > ,
99
+ ) -> QueryResult < ' tcx > ;
100
+
101
+ fn consider_auto_trait_candidate (
102
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
103
+ goal : Goal < ' tcx , Self > ,
104
+ ) -> QueryResult < ' tcx > ;
105
+
106
+ fn consider_trait_alias_candidate (
107
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
108
+ goal : Goal < ' tcx , Self > ,
109
+ ) -> QueryResult < ' tcx > ;
93
110
94
111
fn consider_builtin_sized_candidate (
95
112
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
96
113
goal : Goal < ' tcx , Self > ,
97
- ) -> Result < Certainty , NoSolution > ;
114
+ ) -> QueryResult < ' tcx > ;
98
115
99
- fn consider_assumption (
116
+ fn consider_builtin_copy_clone_candidate (
100
117
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
101
118
goal : Goal < ' tcx , Self > ,
102
- assumption : ty:: Predicate < ' tcx > ,
103
- ) -> Result < Certainty , NoSolution > ;
119
+ ) -> QueryResult < ' tcx > ;
104
120
}
121
+
105
122
impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
106
123
pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < ' tcx > > (
107
124
& mut self ,
@@ -119,6 +136,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
119
136
120
137
self . assemble_alias_bound_candidates ( goal, & mut candidates) ;
121
138
139
+ self . assemble_object_bound_candidates ( goal, & mut candidates) ;
140
+
122
141
candidates
123
142
}
124
143
@@ -180,9 +199,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
180
199
tcx. for_each_relevant_impl (
181
200
goal. predicate . trait_def_id ( tcx) ,
182
201
goal. predicate . self_ty ( ) ,
183
- |impl_def_id| match G :: consider_impl_candidate ( self , goal, impl_def_id)
184
- . and_then ( |certainty| self . make_canonical_response ( certainty) )
185
- {
202
+ |impl_def_id| match G :: consider_impl_candidate ( self , goal, impl_def_id) {
186
203
Ok ( result) => candidates
187
204
. push ( Candidate { source : CandidateSource :: Impl ( impl_def_id) , result } ) ,
188
205
Err ( NoSolution ) => ( ) ,
@@ -197,13 +214,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
197
214
) {
198
215
let lang_items = self . tcx ( ) . lang_items ( ) ;
199
216
let trait_def_id = goal. predicate . trait_def_id ( self . tcx ( ) ) ;
200
- let result = if lang_items. sized_trait ( ) == Some ( trait_def_id) {
217
+ let result = if self . tcx ( ) . trait_is_auto ( trait_def_id) {
218
+ G :: consider_auto_trait_candidate ( self , goal)
219
+ } else if self . tcx ( ) . trait_is_alias ( trait_def_id) {
220
+ G :: consider_trait_alias_candidate ( self , goal)
221
+ } else if lang_items. sized_trait ( ) == Some ( trait_def_id) {
201
222
G :: consider_builtin_sized_candidate ( self , goal)
223
+ } else if lang_items. copy_trait ( ) == Some ( trait_def_id)
224
+ || lang_items. clone_trait ( ) == Some ( trait_def_id)
225
+ {
226
+ G :: consider_builtin_copy_clone_candidate ( self , goal)
202
227
} else {
203
228
Err ( NoSolution )
204
229
} ;
205
230
206
- match result. and_then ( |certainty| self . make_canonical_response ( certainty ) ) {
231
+ match result {
207
232
Ok ( result) => {
208
233
candidates. push ( Candidate { source : CandidateSource :: BuiltinImpl , result } )
209
234
}
@@ -217,9 +242,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
217
242
candidates : & mut Vec < Candidate < ' tcx > > ,
218
243
) {
219
244
for ( i, assumption) in goal. param_env . caller_bounds ( ) . iter ( ) . enumerate ( ) {
220
- match G :: consider_assumption ( self , goal, assumption)
221
- . and_then ( |certainty| self . make_canonical_response ( certainty) )
222
- {
245
+ match G :: consider_assumption ( self , goal, assumption) {
223
246
Ok ( result) => {
224
247
candidates. push ( Candidate { source : CandidateSource :: ParamEnv ( i) , result } )
225
248
}
@@ -268,14 +291,60 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
268
291
. subst_iter_copied ( self . tcx ( ) , alias_ty. substs )
269
292
. enumerate ( )
270
293
{
271
- match G :: consider_assumption ( self , goal, assumption)
272
- . and_then ( |certainty| self . make_canonical_response ( certainty) )
273
- {
294
+ match G :: consider_assumption ( self , goal, assumption) {
274
295
Ok ( result) => {
275
296
candidates. push ( Candidate { source : CandidateSource :: AliasBound ( i) , result } )
276
297
}
277
298
Err ( NoSolution ) => ( ) ,
278
299
}
279
300
}
280
301
}
302
+
303
+ fn assemble_object_bound_candidates < G : GoalKind < ' tcx > > (
304
+ & mut self ,
305
+ goal : Goal < ' tcx , G > ,
306
+ candidates : & mut Vec < Candidate < ' tcx > > ,
307
+ ) {
308
+ let self_ty = goal. predicate . self_ty ( ) ;
309
+ let bounds = match * self_ty. kind ( ) {
310
+ ty:: Bool
311
+ | ty:: Char
312
+ | ty:: Int ( _)
313
+ | ty:: Uint ( _)
314
+ | ty:: Float ( _)
315
+ | ty:: Adt ( _, _)
316
+ | ty:: Foreign ( _)
317
+ | ty:: Str
318
+ | ty:: Array ( _, _)
319
+ | ty:: Slice ( _)
320
+ | ty:: RawPtr ( _)
321
+ | ty:: Ref ( _, _, _)
322
+ | ty:: FnDef ( _, _)
323
+ | ty:: FnPtr ( _)
324
+ | ty:: Alias ( ..)
325
+ | ty:: Closure ( ..)
326
+ | ty:: Generator ( ..)
327
+ | ty:: GeneratorWitness ( _)
328
+ | ty:: Never
329
+ | ty:: Tuple ( _)
330
+ | ty:: Param ( _)
331
+ | ty:: Placeholder ( ..)
332
+ | ty:: Infer ( _)
333
+ | ty:: Error ( _) => return ,
334
+ ty:: Bound ( ..) => bug ! ( "unexpected bound type: {goal:?}" ) ,
335
+ ty:: Dynamic ( bounds, ..) => bounds,
336
+ } ;
337
+
338
+ let tcx = self . tcx ( ) ;
339
+ for assumption in
340
+ elaborate_predicates ( tcx, bounds. iter ( ) . map ( |bound| bound. with_self_ty ( tcx, self_ty) ) )
341
+ {
342
+ match G :: consider_assumption ( self , goal, assumption. predicate ) {
343
+ Ok ( result) => {
344
+ candidates. push ( Candidate { source : CandidateSource :: BuiltinImpl , result } )
345
+ }
346
+ Err ( NoSolution ) => ( ) ,
347
+ }
348
+ }
349
+ }
281
350
}
0 commit comments