@@ -474,26 +474,7 @@ impl<'tcx> Instance<'tcx> {
474
474
}
475
475
476
476
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 ) ;
497
478
debug ! ( "polymorphize: self={:?} polymorphized_substs={:?}" , self , polymorphized_substs) ;
498
479
Self { def : self . def , substs : polymorphized_substs }
499
480
} else {
@@ -502,6 +483,92 @@ impl<'tcx> Instance<'tcx> {
502
483
}
503
484
}
504
485
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
+
505
572
fn needs_fn_once_adapter_shim (
506
573
actual_closure_kind : ty:: ClosureKind ,
507
574
trait_closure_kind : ty:: ClosureKind ,
0 commit comments