@@ -5,9 +5,10 @@ use std::iter;
5
5
use crate :: traits:: TupleArgumentsFlag ;
6
6
7
7
use super :: assembly:: { self , AssemblyCtxt } ;
8
- use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , QueryResult } ;
8
+ use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , MaybeCause , QueryResult } ;
9
+
9
10
use rustc_hir:: def_id:: DefId ;
10
- use rustc_hir:: Unsafety ;
11
+ use rustc_hir:: { Movability , Mutability , Unsafety } ;
11
12
use rustc_infer:: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
12
13
use rustc_infer:: traits:: query:: NoSolution ;
13
14
use rustc_infer:: traits:: util:: supertraits;
@@ -225,20 +226,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
225
226
) {
226
227
// FIXME: We need to give auto trait candidates less precedence than impl candidates?
227
228
acx. infcx . probe ( |_| {
228
- let Ok ( constituent_tys) =
229
- instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) else { return } ;
230
- let nested_goals = constituent_tys
231
- . into_iter ( )
232
- . map ( |ty| {
233
- Goal :: new (
234
- acx. cx . tcx ,
235
- goal. param_env ,
236
- ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
237
- )
238
- } )
239
- . collect ( ) ;
240
- let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
241
- acx. try_insert_candidate ( CandidateSource :: AutoImpl , certainty) ;
229
+ let components =
230
+ instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) ;
231
+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: AutoImpl ) ;
242
232
} )
243
233
}
244
234
@@ -284,36 +274,51 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
284
274
let self_ty = goal. predicate . self_ty ( ) ;
285
275
286
276
if Some ( trait_def_id) == lang_items. sized_trait ( ) {
287
- if self_ty. is_trivially_sized ( acx. cx . tcx ) {
288
- acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
289
- }
277
+ acx. infcx . probe ( |_| {
278
+ let components = instantiate_constituent_tys_for_sized_trait ( acx. infcx , self_ty) ;
279
+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: Builtin ) ;
280
+ } )
290
281
} else if Some ( trait_def_id) == lang_items. copy_trait ( )
291
282
|| Some ( trait_def_id) == lang_items. clone_trait ( )
292
283
{
293
- // FIXME
284
+ acx. infcx . probe ( |_| {
285
+ let components =
286
+ instantiate_constituent_tys_for_copy_clone_trait ( acx. infcx , self_ty) ;
287
+ evaluate_goal_for_components ( acx, goal, components, CandidateSource :: Builtin ) ;
288
+ } )
294
289
} else if Some ( trait_def_id) == lang_items. discriminant_kind_trait ( )
295
290
|| Some ( trait_def_id) == lang_items. pointee_trait ( )
296
291
{
297
292
// `Pointee` and `DiscriminantKind` are implemented by all traits unconditionally
298
293
acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
299
294
} else if Some ( trait_def_id) == lang_items. tuple_trait ( ) {
300
295
match * self_ty. kind ( ) {
301
- ty:: Infer ( ty:: TyVar ( _) ) => todo ! ( "ambiguous" ) ,
296
+ ty:: Infer ( ty:: TyVar ( _) ) => acx. try_insert_candidate (
297
+ CandidateSource :: Builtin ,
298
+ Certainty :: Maybe ( MaybeCause :: Ambiguity ) ,
299
+ ) ,
302
300
ty:: Tuple ( _) => acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ,
303
301
_ => { }
304
302
}
305
303
} else if Some ( trait_def_id) == lang_items. pointer_sized ( ) {
306
304
let erased_self_ty = acx. cx . tcx . erase_regions ( self_ty) ;
307
305
if erased_self_ty. has_non_region_infer ( ) {
308
- todo ! ( "ambiguous" )
309
- }
310
- let usize_layout =
311
- acx. cx . tcx . layout_of ( ty:: ParamEnv :: empty ( ) . and ( acx. cx . tcx . types . usize ) ) . unwrap ( ) ;
312
- if let Ok ( layout) = acx. cx . tcx . layout_of ( goal. param_env . and ( self_ty) )
313
- && layout. layout . size ( ) == usize_layout. layout . size ( )
314
- && layout. layout . align ( ) . abi == usize_layout. layout . align ( ) . abi
315
- {
316
- acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
306
+ acx. try_insert_candidate (
307
+ CandidateSource :: Builtin ,
308
+ Certainty :: Maybe ( MaybeCause :: Ambiguity ) ,
309
+ )
310
+ } else {
311
+ let usize_layout = acx
312
+ . cx
313
+ . tcx
314
+ . layout_of ( ty:: ParamEnv :: empty ( ) . and ( acx. cx . tcx . types . usize ) )
315
+ . unwrap ( ) ;
316
+ if let Ok ( layout) = acx. cx . tcx . layout_of ( goal. param_env . and ( self_ty) )
317
+ && layout. layout . size ( ) == usize_layout. layout . size ( )
318
+ && layout. layout . align ( ) . abi == usize_layout. layout . align ( ) . abi
319
+ {
320
+ acx. try_insert_candidate ( CandidateSource :: Builtin , Certainty :: Yes ) ;
321
+ }
317
322
}
318
323
} else if Some ( trait_def_id) == lang_items. coerce_unsized_trait ( )
319
324
|| Some ( trait_def_id) == lang_items. unsize_trait ( )
@@ -327,7 +332,7 @@ fn match_poly_trait_ref_against_goal<'tcx>(
327
332
acx : & mut AssemblyCtxt < ' _ , ' tcx , TraitPredicate < ' tcx > > ,
328
333
goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
329
334
trait_ref : ty:: PolyTraitRef < ' tcx > ,
330
- candidate : impl FnOnce ( ) -> CandidateSource ,
335
+ candidate : CandidateSource ,
331
336
) {
332
337
acx. infcx . probe ( |_| {
333
338
let trait_ref = acx. infcx . replace_bound_vars_with_fresh_vars (
@@ -349,18 +354,57 @@ fn match_poly_trait_ref_against_goal<'tcx>(
349
354
let nested_goals = obligations. into_iter ( ) . map ( |o| o. into ( ) ) . collect ( ) ;
350
355
351
356
let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
352
- acx. try_insert_candidate ( candidate ( ) , certainty) ;
357
+ acx. try_insert_candidate ( candidate, certainty) ;
353
358
} )
354
359
}
355
360
361
+ // Evaluate the goal with a new set of self types, combined with a certainty.
362
+ fn evaluate_goal_for_components < ' tcx > (
363
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , TraitPredicate < ' tcx > > ,
364
+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
365
+ components : ComponentsAndCertainty < ' tcx > ,
366
+ candidate : CandidateSource ,
367
+ ) {
368
+ let components = match components {
369
+ ComponentsAndCertainty :: Yes ( components) => components,
370
+ ComponentsAndCertainty :: Maybe => {
371
+ acx. try_insert_candidate ( candidate, Certainty :: Maybe ( MaybeCause :: Ambiguity ) ) ;
372
+ return ;
373
+ }
374
+ ComponentsAndCertainty :: No => {
375
+ return ;
376
+ }
377
+ } ;
378
+
379
+ let nested_goals = components
380
+ . into_iter ( )
381
+ . map ( |ty| {
382
+ Goal :: new (
383
+ acx. cx . tcx ,
384
+ goal. param_env ,
385
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
386
+ )
387
+ } )
388
+ . collect ( ) ;
389
+
390
+ let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
391
+ acx. try_insert_candidate ( candidate, certainty) ;
392
+ }
393
+
394
+ enum ComponentsAndCertainty < ' tcx > {
395
+ Yes ( Vec < Ty < ' tcx > > ) ,
396
+ Maybe ,
397
+ No ,
398
+ }
399
+
356
400
// Calculates the constituent types of a type for `auto trait` purposes.
357
401
//
358
402
// For types with an "existential" binder, i.e. generator witnesses, we also
359
403
// instantiate the binder with placeholders eagerly.
360
404
fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
361
405
infcx : & InferCtxt < ' tcx > ,
362
406
ty : Ty < ' tcx > ,
363
- ) -> Result < Vec < Ty < ' tcx > > , ( ) > {
407
+ ) -> ComponentsAndCertainty < ' tcx > {
364
408
let tcx = infcx. tcx ;
365
409
match * ty. kind ( ) {
366
410
ty:: Uint ( _)
@@ -373,53 +417,179 @@ fn instantiate_constituent_tys_for_auto_trait<'tcx>(
373
417
| ty:: Error ( _)
374
418
| ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
375
419
| ty:: Never
376
- | ty:: Char => Ok ( vec ! [ ] ) ,
420
+ | ty:: Char => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
377
421
378
422
ty:: Placeholder ( ..)
379
423
| ty:: Dynamic ( ..)
380
424
| ty:: Param ( ..)
381
425
| ty:: Foreign ( ..)
382
426
| ty:: Alias ( ty:: Projection , ..)
383
- | ty:: Bound ( ..)
384
- | ty:: Infer ( ty:: TyVar ( _) ) => {
385
- // FIXME: Do we need to mark anything as ambiguous here? Yeah?
386
- Err ( ( ) )
387
- }
427
+ | ty:: Bound ( ..) => ComponentsAndCertainty :: No ,
428
+
429
+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
388
430
389
431
ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
390
432
391
433
ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
392
- Ok ( vec ! [ element_ty] )
434
+ ComponentsAndCertainty :: Yes ( vec ! [ element_ty] )
393
435
}
394
436
395
- ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
437
+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => {
438
+ ComponentsAndCertainty :: Yes ( vec ! [ element_ty] )
439
+ }
396
440
397
441
ty:: Tuple ( ref tys) => {
398
442
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
399
- Ok ( tys. iter ( ) . collect ( ) )
443
+ ComponentsAndCertainty :: Yes ( tys. iter ( ) . collect ( ) )
400
444
}
401
445
402
- ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
446
+ ty:: Closure ( _, ref substs) => {
447
+ ComponentsAndCertainty :: Yes ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] )
448
+ }
403
449
404
450
ty:: Generator ( _, ref substs, _) => {
405
451
let generator_substs = substs. as_generator ( ) ;
406
- Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
452
+ ComponentsAndCertainty :: Yes ( vec ! [
453
+ generator_substs. tupled_upvars_ty( ) ,
454
+ generator_substs. witness( ) ,
455
+ ] )
407
456
}
408
457
409
458
ty:: GeneratorWitness ( types) => {
410
- Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
459
+ ComponentsAndCertainty :: Yes ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
411
460
}
412
461
413
462
// For `PhantomData<T>`, we pass `T`.
414
- ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
463
+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => {
464
+ ComponentsAndCertainty :: Yes ( vec ! [ substs. type_at( 0 ) ] )
465
+ }
415
466
416
- ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
467
+ ty:: Adt ( def, substs) => {
468
+ ComponentsAndCertainty :: Yes ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) )
469
+ }
417
470
418
471
ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
419
472
// We can resolve the `impl Trait` to its concrete type,
420
473
// which enforces a DAG between the functions requiring
421
474
// the auto trait bounds in question.
422
- Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
475
+ ComponentsAndCertainty :: Yes ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
476
+ }
477
+ }
478
+ }
479
+
480
+ fn instantiate_constituent_tys_for_sized_trait < ' tcx > (
481
+ infcx : & InferCtxt < ' tcx > ,
482
+ ty : Ty < ' tcx > ,
483
+ ) -> ComponentsAndCertainty < ' tcx > {
484
+ match * ty. kind ( ) {
485
+ ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
486
+ | ty:: Uint ( _)
487
+ | ty:: Int ( _)
488
+ | ty:: Bool
489
+ | ty:: Float ( _)
490
+ | ty:: FnDef ( ..)
491
+ | ty:: FnPtr ( _)
492
+ | ty:: RawPtr ( ..)
493
+ | ty:: Char
494
+ | ty:: Ref ( ..)
495
+ | ty:: Generator ( ..)
496
+ | ty:: GeneratorWitness ( ..)
497
+ | ty:: Array ( ..)
498
+ | ty:: Closure ( ..)
499
+ | ty:: Never
500
+ | ty:: Dynamic ( _, _, ty:: DynStar )
501
+ | ty:: Error ( _) => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
502
+
503
+ ty:: Str
504
+ | ty:: Slice ( _)
505
+ | ty:: Dynamic ( ..)
506
+ | ty:: Foreign ( ..)
507
+ | ty:: Alias ( ..)
508
+ | ty:: Param ( _) => ComponentsAndCertainty :: No ,
509
+
510
+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
511
+
512
+ ty:: Placeholder ( ..)
513
+ | ty:: Bound ( ..)
514
+ | ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
515
+
516
+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
517
+
518
+ ty:: Adt ( def, substs) => {
519
+ let sized_crit = def. sized_constraint ( infcx. tcx ) ;
520
+ ComponentsAndCertainty :: Yes (
521
+ sized_crit
522
+ . 0
523
+ . iter ( )
524
+ . map ( |ty| sized_crit. rebind ( * ty) . subst ( infcx. tcx , substs) )
525
+ . collect ( ) ,
526
+ )
527
+ }
528
+ }
529
+ }
530
+
531
+ fn instantiate_constituent_tys_for_copy_clone_trait < ' tcx > (
532
+ infcx : & InferCtxt < ' tcx > ,
533
+ ty : Ty < ' tcx > ,
534
+ ) -> ComponentsAndCertainty < ' tcx > {
535
+ match * ty. kind ( ) {
536
+ ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
537
+ | ty:: FnDef ( ..)
538
+ | ty:: FnPtr ( _)
539
+ | ty:: Error ( _) => ComponentsAndCertainty :: Yes ( vec ! [ ] ) ,
540
+
541
+ // Implementations are provided in core
542
+ ty:: Uint ( _)
543
+ | ty:: Int ( _)
544
+ | ty:: Bool
545
+ | ty:: Float ( _)
546
+ | ty:: Char
547
+ | ty:: RawPtr ( ..)
548
+ | ty:: Never
549
+ | ty:: Ref ( _, _, Mutability :: Not )
550
+ | ty:: Array ( ..) => ComponentsAndCertainty :: No ,
551
+
552
+ ty:: Dynamic ( ..)
553
+ | ty:: Str
554
+ | ty:: Slice ( _)
555
+ | ty:: Generator ( _, _, Movability :: Static )
556
+ | ty:: Foreign ( ..)
557
+ | ty:: Ref ( _, _, Mutability :: Mut )
558
+ | ty:: Adt ( _, _)
559
+ | ty:: Alias ( _, _)
560
+ | ty:: Param ( _) => ComponentsAndCertainty :: No ,
561
+
562
+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
563
+
564
+ ty:: Placeholder ( ..)
565
+ | ty:: Bound ( ..)
566
+ | ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
567
+
568
+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
569
+
570
+ ty:: Closure ( _, substs) => match * substs. as_closure ( ) . tupled_upvars_ty ( ) . kind ( ) {
571
+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes ( tys. to_vec ( ) ) ,
572
+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
573
+ _ => bug ! ( ) ,
574
+ } ,
575
+
576
+ ty:: Generator ( _, substs, Movability :: Movable ) => {
577
+ if infcx. tcx . features ( ) . generator_clone {
578
+ let generator = substs. as_generator ( ) ;
579
+ match * generator. tupled_upvars_ty ( ) . kind ( ) {
580
+ ty:: Tuple ( tys) => ComponentsAndCertainty :: Yes (
581
+ tys. iter ( ) . chain ( [ generator. witness ( ) ] ) . collect ( ) ,
582
+ ) ,
583
+ ty:: Infer ( ty:: TyVar ( _) ) => ComponentsAndCertainty :: Maybe ,
584
+ _ => bug ! ( ) ,
585
+ }
586
+ } else {
587
+ ComponentsAndCertainty :: No
588
+ }
589
+ }
590
+
591
+ ty:: GeneratorWitness ( types) => {
592
+ ComponentsAndCertainty :: Yes ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
423
593
}
424
594
}
425
595
}
0 commit comments