@@ -5,7 +5,7 @@ use std::iter;
5
5
use super :: assembly:: { self , AssemblyCtxt } ;
6
6
use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , QueryResult } ;
7
7
use rustc_hir:: def_id:: DefId ;
8
- use rustc_infer:: infer:: { InferOk , LateBoundRegionConversionTime } ;
8
+ use rustc_infer:: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
9
9
use rustc_infer:: traits:: query:: NoSolution ;
10
10
use rustc_infer:: traits:: util:: supertraits;
11
11
use rustc_infer:: traits:: ObligationCause ;
@@ -191,6 +191,29 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
191
191
) ;
192
192
}
193
193
}
194
+
195
+ fn consider_auto_trait_candidate (
196
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
197
+ goal : Goal < ' tcx , Self > ,
198
+ ) {
199
+ // FIXME: We need to give auto trait candidates less precedence than impl candidates?
200
+ acx. infcx . probe ( |_| {
201
+ let Ok ( constituent_tys) =
202
+ instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) else { return } ;
203
+ let nested_goals = constituent_tys
204
+ . into_iter ( )
205
+ . map ( |ty| {
206
+ Goal :: new (
207
+ acx. cx . tcx ,
208
+ goal. param_env ,
209
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
210
+ )
211
+ } )
212
+ . collect ( ) ;
213
+ let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
214
+ acx. try_insert_candidate ( CandidateSource :: AutoImpl , certainty) ;
215
+ } )
216
+ }
194
217
}
195
218
196
219
fn match_poly_trait_ref_against_goal < ' tcx > (
@@ -223,6 +246,77 @@ fn match_poly_trait_ref_against_goal<'tcx>(
223
246
} )
224
247
}
225
248
249
+ // Calculates the constituent types of a type for `auto trait` purposes.
250
+ //
251
+ // For types with an "existential" binder, i.e. generator witnesses, we also
252
+ // instantiate the binder with placeholders eagerly.
253
+ fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
254
+ infcx : & InferCtxt < ' tcx > ,
255
+ ty : Ty < ' tcx > ,
256
+ ) -> Result < Vec < Ty < ' tcx > > , ( ) > {
257
+ let tcx = infcx. tcx ;
258
+ match * ty. kind ( ) {
259
+ ty:: Uint ( _)
260
+ | ty:: Int ( _)
261
+ | ty:: Bool
262
+ | ty:: Float ( _)
263
+ | ty:: FnDef ( ..)
264
+ | ty:: FnPtr ( _)
265
+ | ty:: Str
266
+ | ty:: Error ( _)
267
+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
268
+ | ty:: Never
269
+ | ty:: Char => Ok ( vec ! [ ] ) ,
270
+
271
+ ty:: Placeholder ( ..)
272
+ | ty:: Dynamic ( ..)
273
+ | ty:: Param ( ..)
274
+ | ty:: Foreign ( ..)
275
+ | ty:: Alias ( ty:: Projection , ..)
276
+ | ty:: Bound ( ..)
277
+ | ty:: Infer ( ty:: TyVar ( _) ) => {
278
+ // FIXME: Do we need to mark anything as ambiguous here? Yeah?
279
+ Err ( ( ) )
280
+ }
281
+
282
+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
283
+
284
+ ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
285
+ Ok ( vec ! [ element_ty] )
286
+ }
287
+
288
+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
289
+
290
+ ty:: Tuple ( ref tys) => {
291
+ // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
292
+ Ok ( tys. iter ( ) . collect ( ) )
293
+ }
294
+
295
+ ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
296
+
297
+ ty:: Generator ( _, ref substs, _) => {
298
+ let generator_substs = substs. as_generator ( ) ;
299
+ Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
300
+ }
301
+
302
+ ty:: GeneratorWitness ( types) => {
303
+ Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
304
+ }
305
+
306
+ // For `PhantomData<T>`, we pass `T`.
307
+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
308
+
309
+ ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
310
+
311
+ ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
312
+ // We can resolve the `impl Trait` to its concrete type,
313
+ // which enforces a DAG between the functions requiring
314
+ // the auto trait bounds in question.
315
+ Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
316
+ }
317
+ }
318
+ }
319
+
226
320
impl < ' tcx > EvalCtxt < ' tcx > {
227
321
pub ( super ) fn compute_trait_goal (
228
322
& mut self ,
0 commit comments