@@ -6,7 +6,7 @@ use super::assembly::{self, Candidate, CandidateSource};
6
6
use super :: infcx_ext:: InferCtxtExt ;
7
7
use super :: { EvalCtxt , Goal , QueryResult } ;
8
8
use rustc_hir:: def_id:: DefId ;
9
- use rustc_infer:: infer:: LateBoundRegionConversionTime ;
9
+ use rustc_infer:: infer:: InferCtxt ;
10
10
use rustc_infer:: traits:: query:: NoSolution ;
11
11
use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
12
12
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
@@ -58,13 +58,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
58
58
} )
59
59
}
60
60
61
- fn consider_builtin_sized_candidate (
62
- _ecx : & mut EvalCtxt < ' _ , ' tcx > ,
63
- _goal : Goal < ' tcx , Self > ,
64
- ) -> QueryResult < ' tcx > {
65
- unimplemented ! ( ) ;
66
- }
67
-
68
61
fn consider_assumption (
69
62
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
70
63
goal : Goal < ' tcx , Self > ,
@@ -84,9 +77,61 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
84
77
Err ( NoSolution )
85
78
}
86
79
}
80
+
81
+ fn consider_auto_trait_candidate (
82
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
83
+ goal : Goal < ' tcx , Self > ,
84
+ ) -> QueryResult < ' tcx > {
85
+ ecx. infcx . probe ( |_| {
86
+ let constituent_tys =
87
+ instantiate_constituent_tys_for_auto_trait ( ecx. infcx , goal. predicate . self_ty ( ) ) ?;
88
+ ecx. evaluate_goal_for_constituent_tys_and_make_canonical_response ( goal, constituent_tys)
89
+ } )
90
+ }
91
+
92
+ fn consider_trait_alias_candidate (
93
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
94
+ goal : Goal < ' tcx , Self > ,
95
+ ) -> QueryResult < ' tcx > {
96
+ let tcx = ecx. tcx ( ) ;
97
+
98
+ ecx. infcx . probe ( |_| {
99
+ let nested_obligations = tcx
100
+ . predicates_of ( goal. predicate . def_id ( ) )
101
+ . instantiate ( tcx, goal. predicate . trait_ref . substs ) ;
102
+ ecx. evaluate_all_and_make_canonical_response (
103
+ nested_obligations. predicates . into_iter ( ) . map ( |p| goal. with ( tcx, p) ) . collect ( ) ,
104
+ )
105
+ } )
106
+ }
107
+
108
+ fn consider_builtin_sized_candidate (
109
+ _ecx : & mut EvalCtxt < ' _ , ' tcx > ,
110
+ _goal : Goal < ' tcx , Self > ,
111
+ ) -> QueryResult < ' tcx > {
112
+ unimplemented ! ( ) ;
113
+ }
87
114
}
88
115
89
116
impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
117
+ fn evaluate_goal_for_constituent_tys_and_make_canonical_response (
118
+ & mut self ,
119
+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
120
+ constituent_tys : Vec < Ty < ' tcx > > ,
121
+ ) -> QueryResult < ' tcx > {
122
+ self . evaluate_all_and_make_canonical_response (
123
+ constituent_tys
124
+ . into_iter ( )
125
+ . map ( |ty| {
126
+ goal. with (
127
+ self . tcx ( ) ,
128
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( self . tcx ( ) , ty) ) ,
129
+ )
130
+ } )
131
+ . collect ( ) ,
132
+ )
133
+ }
134
+
90
135
pub ( super ) fn compute_trait_goal (
91
136
& mut self ,
92
137
goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
@@ -162,3 +207,74 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
162
207
candidate
163
208
}
164
209
}
210
+
211
+ // Calculates the constituent types of a type for `auto trait` purposes.
212
+ //
213
+ // For types with an "existential" binder, i.e. generator witnesses, we also
214
+ // instantiate the binder with placeholders eagerly.
215
+ fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
216
+ infcx : & InferCtxt < ' tcx > ,
217
+ ty : Ty < ' tcx > ,
218
+ ) -> Result < Vec < Ty < ' tcx > > , NoSolution > {
219
+ let tcx = infcx. tcx ;
220
+ match * ty. kind ( ) {
221
+ ty:: Uint ( _)
222
+ | ty:: Int ( _)
223
+ | ty:: Bool
224
+ | ty:: Float ( _)
225
+ | ty:: FnDef ( ..)
226
+ | ty:: FnPtr ( _)
227
+ | ty:: Str
228
+ | ty:: Error ( _)
229
+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
230
+ | ty:: Never
231
+ | ty:: Char => Ok ( vec ! [ ] ) ,
232
+
233
+ ty:: Placeholder ( ..)
234
+ | ty:: Dynamic ( ..)
235
+ | ty:: Param ( ..)
236
+ | ty:: Foreign ( ..)
237
+ | ty:: Alias ( ty:: Projection , ..)
238
+ | ty:: Bound ( ..)
239
+ | ty:: Infer ( ty:: TyVar ( _) ) => {
240
+ // FIXME: Do we need to mark anything as ambiguous here? Yeah?
241
+ Err ( NoSolution )
242
+ }
243
+
244
+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
245
+
246
+ ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
247
+ Ok ( vec ! [ element_ty] )
248
+ }
249
+
250
+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
251
+
252
+ ty:: Tuple ( ref tys) => {
253
+ // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
254
+ Ok ( tys. iter ( ) . collect ( ) )
255
+ }
256
+
257
+ ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
258
+
259
+ ty:: Generator ( _, ref substs, _) => {
260
+ let generator_substs = substs. as_generator ( ) ;
261
+ Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
262
+ }
263
+
264
+ ty:: GeneratorWitness ( types) => {
265
+ Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
266
+ }
267
+
268
+ // For `PhantomData<T>`, we pass `T`.
269
+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
270
+
271
+ ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
272
+
273
+ ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
274
+ // We can resolve the `impl Trait` to its concrete type,
275
+ // which enforces a DAG between the functions requiring
276
+ // the auto trait bounds in question.
277
+ Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
278
+ }
279
+ }
280
+ }
0 commit comments