9
9
use rustc_data_structures:: stack:: ensure_sufficient_stack;
10
10
use rustc_hir:: lang_items:: LangItem ;
11
11
use rustc_index:: bit_set:: GrowableBitSet ;
12
+ use rustc_infer:: infer:: LateBoundRegionConversionTime :: HigherRankedType ;
12
13
use rustc_infer:: infer:: { self , InferOk } ;
14
+ use rustc_middle:: ty:: fold:: TypeFolder ;
13
15
use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst , SubstsRef } ;
14
- use rustc_middle:: ty:: { self , Ty } ;
16
+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
15
17
use rustc_middle:: ty:: { ToPolyTraitRef , ToPredicate , WithConstness } ;
16
18
use rustc_span:: def_id:: DefId ;
17
19
18
- use crate :: traits:: project:: { self , normalize_with_depth } ;
20
+ use crate :: traits:: project:: { normalize_with_depth , normalize_with_depth_to } ;
19
21
use crate :: traits:: select:: TraitObligationExt ;
20
22
use crate :: traits:: util;
21
23
use crate :: traits:: util:: { closure_trait_ref_and_return_type, predicate_for_trait_def} ;
@@ -340,16 +342,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
340
342
& mut self ,
341
343
obligation : & TraitObligation < ' tcx > ,
342
344
) -> ImplSourceObjectData < ' tcx , PredicateObligation < ' tcx > > {
345
+ let tcx = self . tcx ( ) ;
343
346
debug ! ( "confirm_object_candidate({:?})" , obligation) ;
344
347
345
- let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
346
- let self_ty = self . infcx . replace_bound_vars_with_placeholders ( & self_ty) ;
348
+ let trait_predicate =
349
+ self . infcx . replace_bound_vars_with_placeholders ( & obligation. predicate ) ;
350
+ let self_ty = self . infcx . shallow_resolve ( trait_predicate. self_ty ( ) ) ;
351
+ let obligation_trait_ref = ty:: Binder :: dummy ( trait_predicate. trait_ref ) ;
347
352
let data = match self_ty. kind ( ) {
348
- ty:: Dynamic ( data, ..) => data,
353
+ ty:: Dynamic ( data, ..) => {
354
+ self . infcx
355
+ . replace_bound_vars_with_fresh_vars (
356
+ obligation. cause . span ,
357
+ HigherRankedType ,
358
+ data,
359
+ )
360
+ . 0
361
+ }
349
362
_ => span_bug ! ( obligation. cause. span, "object candidate with non-object" ) ,
350
363
} ;
351
364
352
- let poly_trait_ref = data
365
+ let object_trait_ref = data
353
366
. principal ( )
354
367
. unwrap_or_else ( || {
355
368
span_bug ! ( obligation. cause. span, "object candidate with no principal" )
@@ -361,24 +374,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
361
374
let vtable_base;
362
375
363
376
{
364
- let tcx = self . tcx ( ) ;
365
-
366
377
// We want to find the first supertrait in the list of
367
378
// supertraits that we can unify with, and do that
368
379
// unification. We know that there is exactly one in the list
369
380
// where we can unify, because otherwise select would have
370
381
// reported an ambiguity. (When we do find a match, also
371
382
// record it for later.)
372
- let nonmatching = util:: supertraits ( tcx, poly_trait_ref) . take_while ( |& t| {
373
- match self . infcx . commit_if_ok ( |_| self . match_poly_trait_ref ( obligation, t) ) {
374
- Ok ( obligations) => {
375
- upcast_trait_ref = Some ( t) ;
376
- nested. extend ( obligations) ;
377
- false
383
+ let nonmatching = util:: supertraits ( tcx, ty:: Binder :: dummy ( object_trait_ref) )
384
+ . take_while ( |& t| {
385
+ match self . infcx . commit_if_ok ( |_| {
386
+ self . infcx
387
+ . at ( & obligation. cause , obligation. param_env )
388
+ . sup ( obligation_trait_ref, t)
389
+ . map ( |InferOk { obligations, .. } | obligations)
390
+ . map_err ( |_| ( ) )
391
+ } ) {
392
+ Ok ( obligations) => {
393
+ upcast_trait_ref = Some ( t) ;
394
+ nested. extend ( obligations) ;
395
+ false
396
+ }
397
+ Err ( _) => true ,
378
398
}
379
- Err ( _) => true ,
380
- }
381
- } ) ;
399
+ } ) ;
382
400
383
401
// Additionally, for each of the non-matching predicates that
384
402
// we pass over, we sum up the set of number of vtable
@@ -387,47 +405,105 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
387
405
vtable_base = nonmatching. map ( |t| super :: util:: count_own_vtable_entries ( tcx, t) ) . sum ( ) ;
388
406
}
389
407
390
- for bound in data. skip_binder ( ) {
391
- match bound {
392
- ty:: ExistentialPredicate :: Projection ( projection) => {
393
- // This maybe belongs in wf, but that can't (doesn't) handle
394
- // higher-ranked things.
395
- // Prevent, e.g., `dyn Iterator<Item = str>`.
396
- // FIXME(generic_associated_types): We need some way to
397
- // ensure that for `dyn for<'a> X<Item<'a> = &'a ()>` the
398
- // bound holds for all `'a`.
399
- let ( infer_projection, _) = self . infcx . replace_bound_vars_with_fresh_vars (
408
+ // Check supertraits hold
409
+ nested. extend ( util:: supertraits ( tcx, obligation_trait_ref) . skip ( 1 ) . map ( |super_trait| {
410
+ Obligation :: new (
411
+ obligation. cause . clone ( ) ,
412
+ obligation. param_env ,
413
+ super_trait. without_const ( ) . to_predicate ( tcx) ,
414
+ )
415
+ } ) ) ;
416
+
417
+ let upcast_trait_ref = upcast_trait_ref. unwrap ( ) ;
418
+
419
+ let assoc_types: Vec < _ > = tcx
420
+ . associated_items ( upcast_trait_ref. def_id ( ) )
421
+ . in_definition_order ( )
422
+ . filter_map (
423
+ |item| if item. kind == ty:: AssocKind :: Type { Some ( item. def_id ) } else { None } ,
424
+ )
425
+ . collect ( ) ;
426
+
427
+ if !assoc_types. is_empty ( ) {
428
+ let predicates: Vec < _ > =
429
+ data. iter ( )
430
+ . filter_map ( |pred| match pred {
431
+ ty:: ExistentialPredicate :: Projection ( proj) => {
432
+ if assoc_types. contains ( & proj. item_def_id ) {
433
+ match self . infcx . commit_if_ok ( |_| {
434
+ self . infcx
435
+ . at ( & obligation. cause , obligation. param_env )
436
+ . sup (
437
+ ty:: Binder :: dummy (
438
+ proj. trait_ref ( tcx) . with_self_ty ( tcx, self_ty) ,
439
+ ) ,
440
+ upcast_trait_ref,
441
+ )
442
+ . map ( |InferOk { obligations, .. } | obligations)
443
+ . map_err ( |_| ( ) )
444
+ } ) {
445
+ Ok ( obligations) => {
446
+ nested. extend ( obligations) ;
447
+ Some ( proj)
448
+ }
449
+ Err ( _) => None ,
450
+ }
451
+ } else {
452
+ None
453
+ }
454
+ }
455
+ ty:: ExistentialPredicate :: AutoTrait ( _)
456
+ | ty:: ExistentialPredicate :: Trait ( _) => None ,
457
+ } )
458
+ . collect ( ) ;
459
+
460
+ let upcast_trait_ref = upcast_trait_ref
461
+ . no_bound_vars ( )
462
+ . expect ( "sup shouldn't return binder with bound vars" ) ;
463
+ let mut normalizer = ObjectAssociatedTypeNormalizer {
464
+ infcx : self . infcx ,
465
+ object_ty : self_ty,
466
+ object_bounds : & predicates,
467
+ param_env : obligation. param_env ,
468
+ cause : & obligation. cause ,
469
+ nested : & mut nested,
470
+ } ;
471
+ for assoc_type in assoc_types {
472
+ if !tcx. generics_of ( assoc_type) . params . is_empty ( ) {
473
+ // FIXME(generic_associated_types) generate placeholders to
474
+ // extend the trait substs.
475
+ tcx. sess . span_fatal (
400
476
obligation. cause . span ,
401
- infer:: HigherRankedType ,
402
- & ty:: Binder :: bind ( projection) ,
477
+ "generic associated types in trait objects are not supported yet" ,
403
478
) ;
404
- let substs: Vec < _ > =
405
- iter:: once ( self_ty. into ( ) ) . chain ( infer_projection. substs ) . collect ( ) ;
406
- let bounds =
407
- self . tcx ( ) . item_bounds ( projection. item_def_id ) . iter ( ) . map ( |bound| {
408
- // In the example above, `bound` is `<Self as Iterator>::Item: Sized`
409
- // `subst_bound` is `str: Sized`.
410
- let subst_bound = util:: subst_assoc_item_bound (
411
- self . tcx ( ) ,
412
- bound,
413
- infer_projection. ty ,
414
- & substs,
415
- ) ;
416
- Obligation :: new (
417
- obligation. cause . clone ( ) ,
418
- obligation. param_env . clone ( ) ,
419
- subst_bound,
420
- )
421
- } ) ;
422
- debug ! ( "confirm_object_candidate: adding bounds: {:?}" , bounds) ;
423
- nested. extend ( bounds) ;
424
479
}
425
- ty:: ExistentialPredicate :: Trait ( _) | ty:: ExistentialPredicate :: AutoTrait ( _) => { }
480
+ // This maybe belongs in wf, but that can't (doesn't) handle
481
+ // higher-ranked things.
482
+ // Prevent, e.g., `dyn Iterator<Item = str>`.
483
+ for bound in self . tcx ( ) . item_bounds ( assoc_type) {
484
+ let subst_bound = bound. subst ( tcx, upcast_trait_ref. substs ) ;
485
+ // Normalize projections the trait object manually to
486
+ // avoid evaluation overflow.
487
+ let object_normalized = subst_bound. fold_with ( & mut normalizer) ;
488
+ let normalized_bound = normalize_with_depth_to (
489
+ self ,
490
+ obligation. param_env ,
491
+ obligation. cause . clone ( ) ,
492
+ obligation. recursion_depth + 1 ,
493
+ & object_normalized,
494
+ normalizer. nested ,
495
+ ) ;
496
+ normalizer. nested . push ( Obligation :: new (
497
+ obligation. cause . clone ( ) ,
498
+ obligation. param_env . clone ( ) ,
499
+ normalized_bound,
500
+ ) ) ;
501
+ }
426
502
}
427
503
}
428
504
429
505
debug ! ( "confirm_object_candidate: nested: {:?}" , nested) ;
430
- ImplSourceObjectData { upcast_trait_ref : upcast_trait_ref . unwrap ( ) , vtable_base, nested }
506
+ ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }
431
507
}
432
508
433
509
fn confirm_fn_pointer_candidate (
@@ -450,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
450
526
. map_bound ( |( trait_ref, _) | trait_ref) ;
451
527
452
528
let Normalized { value : trait_ref, mut obligations } = ensure_sufficient_stack ( || {
453
- project :: normalize_with_depth (
529
+ normalize_with_depth (
454
530
self ,
455
531
obligation. param_env ,
456
532
obligation. cause . clone ( ) ,
@@ -867,3 +943,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
867
943
Ok ( ImplSourceBuiltinData { nested } )
868
944
}
869
945
}
946
+
947
+ struct ObjectAssociatedTypeNormalizer < ' a , ' tcx > {
948
+ infcx : & ' a infer:: InferCtxt < ' a , ' tcx > ,
949
+ object_ty : Ty < ' tcx > ,
950
+ object_bounds : & ' a [ ty:: ExistentialProjection < ' tcx > ] ,
951
+ param_env : ty:: ParamEnv < ' tcx > ,
952
+ cause : & ' a ObligationCause < ' tcx > ,
953
+ nested : & ' a mut Vec < PredicateObligation < ' tcx > > ,
954
+ }
955
+
956
+ impl < ' tcx > TypeFolder < ' tcx > for ObjectAssociatedTypeNormalizer < ' _ , ' tcx > {
957
+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
958
+ self . infcx . tcx
959
+ }
960
+
961
+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
962
+ if !t. has_projections ( ) {
963
+ return t;
964
+ }
965
+ if let ty:: Projection ( proj) = t. kind {
966
+ if let ty:: Dynamic ( ..) = proj. self_ty ( ) . kind {
967
+ for bound in self . object_bounds {
968
+ if proj. item_def_id == bound. item_def_id {
969
+ // FIXME(generic_associated_types): This isn't relating
970
+ // the substs for the associated type.
971
+ match self . infcx . commit_if_ok ( |_| {
972
+ self . infcx . at ( self . cause , self . param_env ) . sub (
973
+ bound
974
+ . with_self_ty ( self . infcx . tcx , self . object_ty )
975
+ . projection_ty
976
+ . trait_ref ( self . infcx . tcx ) ,
977
+ proj. trait_ref ( self . infcx . tcx ) ,
978
+ )
979
+ } ) {
980
+ Ok ( InferOk { value : ( ) , obligations } ) => {
981
+ self . nested . extend ( obligations) ;
982
+ return bound. ty ;
983
+ }
984
+ Err ( _) => { }
985
+ }
986
+ }
987
+ }
988
+ }
989
+ }
990
+ t. super_fold_with ( self )
991
+ }
992
+ }
0 commit comments