99use rustc_data_structures:: stack:: ensure_sufficient_stack;
1010use rustc_hir:: lang_items:: LangItem ;
1111use rustc_index:: bit_set:: GrowableBitSet ;
12+ use rustc_infer:: infer:: LateBoundRegionConversionTime :: HigherRankedType ;
1213use rustc_infer:: infer:: { self , InferOk } ;
14+ use rustc_middle:: ty:: fold:: TypeFolder ;
1315use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst , SubstsRef } ;
14- use rustc_middle:: ty:: { self , Ty } ;
16+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
1517use rustc_middle:: ty:: { ToPolyTraitRef , ToPredicate , WithConstness } ;
1618use rustc_span:: def_id:: DefId ;
1719
18- use crate :: traits:: project:: { self , normalize_with_depth } ;
20+ use crate :: traits:: project:: { normalize_with_depth , normalize_with_depth_to } ;
1921use crate :: traits:: select:: TraitObligationExt ;
2022use crate :: traits:: util;
2123use crate :: traits:: util:: { closure_trait_ref_and_return_type, predicate_for_trait_def} ;
@@ -340,16 +342,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
340342 & mut self ,
341343 obligation : & TraitObligation < ' tcx > ,
342344 ) -> ImplSourceObjectData < ' tcx , PredicateObligation < ' tcx > > {
345+ let tcx = self . tcx ( ) ;
343346 debug ! ( "confirm_object_candidate({:?})" , obligation) ;
344347
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 ) ;
347352 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+ }
349362 _ => span_bug ! ( obligation. cause. span, "object candidate with non-object" ) ,
350363 } ;
351364
352- let poly_trait_ref = data
365+ let object_trait_ref = data
353366 . principal ( )
354367 . unwrap_or_else ( || {
355368 span_bug ! ( obligation. cause. span, "object candidate with no principal" )
@@ -361,24 +374,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
361374 let vtable_base;
362375
363376 {
364- let tcx = self . tcx ( ) ;
365-
366377 // We want to find the first supertrait in the list of
367378 // supertraits that we can unify with, and do that
368379 // unification. We know that there is exactly one in the list
369380 // where we can unify, because otherwise select would have
370381 // reported an ambiguity. (When we do find a match, also
371382 // 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 ,
378398 }
379- Err ( _) => true ,
380- }
381- } ) ;
399+ } ) ;
382400
383401 // Additionally, for each of the non-matching predicates that
384402 // we pass over, we sum up the set of number of vtable
@@ -387,47 +405,105 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
387405 vtable_base = nonmatching. map ( |t| super :: util:: count_own_vtable_entries ( tcx, t) ) . sum ( ) ;
388406 }
389407
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 (
400476 obligation. cause . span ,
401- infer:: HigherRankedType ,
402- & ty:: Binder :: bind ( projection) ,
477+ "generic associated types in trait objects are not supported yet" ,
403478 ) ;
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) ;
424479 }
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+ }
426502 }
427503 }
428504
429505 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 }
431507 }
432508
433509 fn confirm_fn_pointer_candidate (
@@ -450,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
450526 . map_bound ( |( trait_ref, _) | trait_ref) ;
451527
452528 let Normalized { value : trait_ref, mut obligations } = ensure_sufficient_stack ( || {
453- project :: normalize_with_depth (
529+ normalize_with_depth (
454530 self ,
455531 obligation. param_env ,
456532 obligation. cause . clone ( ) ,
@@ -867,3 +943,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
867943 Ok ( ImplSourceBuiltinData { nested } )
868944 }
869945}
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