@@ -485,38 +485,59 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
485485 mut self ,
486486 predicates : & ' tcx ty:: List < ty:: Binder < ' tcx , ty:: ExistentialPredicate < ' tcx > > > ,
487487 ) -> Result < Self :: DynExistential , Self :: Error > {
488- let mut predicate_iter = predicates. iter ( ) . peekable ( ) ;
489- while let Some ( predicate) = predicate_iter. next ( ) {
490- match predicate. as_ref ( ) . skip_binder ( ) {
491- ty:: ExistentialPredicate :: Trait ( trait_ref) => {
492- self = self . in_binder ( & predicate, |mut cx, _predicate| {
488+ // Okay, so this is a bit tricky. Imagine we have a trait object like
489+ // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the
490+ // output looks really close to the syntax, where the `Bar = &'a ()` bit
491+ // is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we
492+ // actually desugar these into two separate `ExistentialPredicate`s. We
493+ // can't enter/exit the "binder scope" twice though, because then we
494+ // would mangle the binders twice. (Also, side note, we merging these
495+ // two is kind of difficult, because of potential HRTBs in the Projection
496+ // predicate.)
497+ //
498+ // Also worth mentioning: imagine that we instead had
499+ // `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is
500+ // under the same binders as `Foo`. Currently, this doesn't matter,
501+ // because only *auto traits* are allowed other than the principal trait
502+ // and all auto traits don't have any generics. Two things could
503+ // make this not an "okay" mangling:
504+ // 1) Instead of mangling only *used*
505+ // bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a
506+ // valid trait predicate);
507+ // 2) We allow multiple "principal" traits in the future, or at least
508+ // allow in any form another trait predicate that can take generics.
509+ //
510+ // Here we assume that predicates have the following structure:
511+ // [<Trait> [{<Projection>}]] [{<Auto>}]
512+ // Since any predicates after the first one shouldn't change the binders,
513+ // just put them all in the binders of the first.
514+ self = self . in_binder ( & predicates[ 0 ] , |mut cx, _| {
515+ for predicate in predicates. iter ( ) {
516+ // It would be nice to be able to validate bound vars here, but
517+ // projections can actually include bound vars from super traits
518+ // because of HRTBs (only in the `Self` type). Also, auto traits
519+ // could have different bound vars *anyways*.
520+ match predicate. as_ref ( ) . skip_binder ( ) {
521+ ty:: ExistentialPredicate :: Trait ( trait_ref) => {
493522 // Use a type that can't appear in defaults of type parameters.
494523 let dummy_self = cx. tcx . mk_ty_infer ( ty:: FreshTy ( 0 ) ) ;
495524 let trait_ref = trait_ref. with_self_ty ( cx. tcx , dummy_self) ;
496525 cx = cx. print_def_path ( trait_ref. def_id , trait_ref. substs ) ?;
497- while let Some ( projection_pred) = predicate_iter. next_if ( |p| {
498- matches ! ( p. skip_binder( ) , ty:: ExistentialPredicate :: Projection ( _) )
499- } ) {
500- let projection = match projection_pred. skip_binder ( ) {
501- ty:: ExistentialPredicate :: Projection ( projection) => projection,
502- _ => unreachable ! ( ) ,
503- } ;
504- let name = cx. tcx . associated_item ( projection. item_def_id ) . ident ;
505- cx. push ( "p" ) ;
506- cx. push_ident ( & name. as_str ( ) ) ;
507- cx = projection. ty . print ( cx) ?;
508- }
509- Ok ( cx)
510- } ) ?;
511- }
512- ty:: ExistentialPredicate :: Projection ( _) => {
513- unreachable ! ( "handled in trait predicate arm" )
514- }
515- ty:: ExistentialPredicate :: AutoTrait ( def_id) => {
516- self = self . print_def_path ( * def_id, & [ ] ) ?;
526+ }
527+ ty:: ExistentialPredicate :: Projection ( projection) => {
528+ let name = cx. tcx . associated_item ( projection. item_def_id ) . ident ;
529+ cx. push ( "p" ) ;
530+ cx. push_ident ( & name. as_str ( ) ) ;
531+ cx = projection. ty . print ( cx) ?;
532+ }
533+ ty:: ExistentialPredicate :: AutoTrait ( def_id) => {
534+ cx = cx. print_def_path ( * def_id, & [ ] ) ?;
535+ }
517536 }
518537 }
519- }
538+ Ok ( cx)
539+ } ) ?;
540+
520541 self . push ( "E" ) ;
521542 Ok ( self )
522543 }
0 commit comments