@@ -474,26 +474,7 @@ impl<'tcx> Instance<'tcx> {
474474 }
475475
476476 if let InstanceDef :: Item ( def) = self . def {
477- let unused = tcx. unused_generic_params ( def. did ) ;
478-
479- if unused. is_empty ( ) {
480- // Exit early if every parameter was used.
481- return self ;
482- }
483-
484- debug ! ( "polymorphize: unused={:?}" , unused) ;
485- let polymorphized_substs =
486- InternalSubsts :: for_item ( tcx, def. did , |param, _| match param. kind {
487- // If parameter is a const or type parameter..
488- ty:: GenericParamDefKind :: Const | ty:: GenericParamDefKind :: Type { .. } if
489- // ..and is within range and unused..
490- unused. contains ( param. index ) . unwrap_or ( false ) =>
491- // ..then use the identity for this parameter.
492- tcx. mk_param_from_def ( param) ,
493- // Otherwise, use the parameter as before.
494- _ => self . substs [ param. index as usize ] ,
495- } ) ;
496-
477+ let polymorphized_substs = polymorphize ( tcx, def. did , self . substs ) ;
497478 debug ! ( "polymorphize: self={:?} polymorphized_substs={:?}" , self , polymorphized_substs) ;
498479 Self { def : self . def , substs : polymorphized_substs }
499480 } else {
@@ -502,6 +483,92 @@ impl<'tcx> Instance<'tcx> {
502483 }
503484}
504485
486+ fn polymorphize < ' tcx > (
487+ tcx : TyCtxt < ' tcx > ,
488+ def_id : DefId ,
489+ substs : SubstsRef < ' tcx > ,
490+ ) -> SubstsRef < ' tcx > {
491+ debug ! ( "polymorphize({:?}, {:?})" , def_id, substs) ;
492+ let unused = tcx. unused_generic_params ( def_id) ;
493+ debug ! ( "polymorphize: unused={:?}" , unused) ;
494+
495+ if unused. is_empty ( ) {
496+ // Exit early if every parameter was used.
497+ return substs;
498+ }
499+
500+ // If this is a closure or generator then we need to handle the case where another closure
501+ // from the function is captured as an upvar and hasn't been polymorphized. In this case,
502+ // the unpolymorphized upvar closure would result in a polymorphized closure producing
503+ // multiple mono items (and eventually symbol clashes).
504+ let upvars_ty = if tcx. is_closure ( def_id) {
505+ Some ( substs. as_closure ( ) . tupled_upvars_ty ( ) )
506+ } else if tcx. type_of ( def_id) . is_generator ( ) {
507+ Some ( substs. as_generator ( ) . tupled_upvars_ty ( ) )
508+ } else {
509+ None
510+ } ;
511+ let has_upvars = upvars_ty. map ( |ty| ty. tuple_fields ( ) . count ( ) > 0 ) . unwrap_or ( false ) ;
512+ debug ! ( "polymorphize: upvars_ty={:?} has_upvars={:?}" , upvars_ty, has_upvars) ;
513+
514+ struct PolymorphizationFolder < ' tcx > {
515+ tcx : TyCtxt < ' tcx > ,
516+ } ;
517+
518+ impl ty:: TypeFolder < ' tcx > for PolymorphizationFolder < ' tcx > {
519+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
520+ self . tcx
521+ }
522+
523+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
524+ debug ! ( "fold_ty: ty={:?}" , ty) ;
525+ match ty. kind {
526+ ty:: Closure ( def_id, substs) => {
527+ let polymorphized_substs = polymorphize ( self . tcx , def_id, substs) ;
528+ self . tcx . mk_closure ( def_id, polymorphized_substs)
529+ }
530+ ty:: Generator ( def_id, substs, movability) => {
531+ let polymorphized_substs = polymorphize ( self . tcx , def_id, substs) ;
532+ self . tcx . mk_generator ( def_id, polymorphized_substs, movability)
533+ }
534+ _ => ty. super_fold_with ( self ) ,
535+ }
536+ }
537+ }
538+
539+ InternalSubsts :: for_item ( tcx, def_id, |param, _| {
540+ let is_unused = unused. contains ( param. index ) . unwrap_or ( false ) ;
541+ debug ! ( "polymorphize: param={:?} is_unused={:?}" , param, is_unused) ;
542+ match param. kind {
543+ // Upvar case: If parameter is a type parameter..
544+ ty:: GenericParamDefKind :: Type { .. } if
545+ // ..and has upvars..
546+ has_upvars &&
547+ // ..and this param has the same type as the tupled upvars..
548+ upvars_ty == Some ( substs[ param. index as usize ] . expect_ty ( ) ) => {
549+ // ..then double-check that polymorphization marked it used..
550+ debug_assert ! ( !is_unused) ;
551+ // ..and polymorphize any closures/generators captured as upvars.
552+ let upvars_ty = upvars_ty. unwrap ( ) ;
553+ let polymorphized_upvars_ty = upvars_ty. fold_with (
554+ & mut PolymorphizationFolder { tcx } ) ;
555+ debug ! ( "polymorphize: polymorphized_upvars_ty={:?}" , polymorphized_upvars_ty) ;
556+ ty:: GenericArg :: from ( polymorphized_upvars_ty)
557+ } ,
558+
559+ // Simple case: If parameter is a const or type parameter..
560+ ty:: GenericParamDefKind :: Const | ty:: GenericParamDefKind :: Type { .. } if
561+ // ..and is within range and unused..
562+ unused. contains ( param. index ) . unwrap_or ( false ) =>
563+ // ..then use the identity for this parameter.
564+ tcx. mk_param_from_def ( param) ,
565+
566+ // Otherwise, use the parameter as before.
567+ _ => substs[ param. index as usize ] ,
568+ }
569+ } )
570+ }
571+
505572fn needs_fn_once_adapter_shim (
506573 actual_closure_kind : ty:: ClosureKind ,
507574 trait_closure_kind : ty:: ClosureKind ,
0 commit comments