Skip to content

Commit fd41bde

Browse files
committed
instance: only polymorphize upvar substs
This commit restricts the substitution polymorphization added in #75255 to only apply to the tupled upvar substitution, rather than all substitutions, fixing a bunch of regressions when polymorphization is enabled. Signed-off-by: David Wood <david@davidtw.co>
1 parent 8e73853 commit fd41bde

File tree

5 files changed

+33
-88
lines changed

5 files changed

+33
-88
lines changed

src/librustc_middle/ty/flags.rs

-6
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ impl FlagComputation {
8585
}
8686

8787
&ty::Generator(_, ref substs, _) => {
88-
self.add_flags(TypeFlags::MAY_POLYMORPHIZE);
89-
9088
let substs = substs.as_generator();
9189
let should_remove_further_specializable =
9290
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
@@ -109,8 +107,6 @@ impl FlagComputation {
109107
}
110108

111109
&ty::Closure(_, substs) => {
112-
self.add_flags(TypeFlags::MAY_POLYMORPHIZE);
113-
114110
let substs = substs.as_closure();
115111
let should_remove_further_specializable =
116112
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
@@ -196,8 +192,6 @@ impl FlagComputation {
196192
}
197193

198194
&ty::FnDef(_, substs) => {
199-
self.add_flags(TypeFlags::MAY_POLYMORPHIZE);
200-
201195
self.add_substs(substs);
202196
}
203197

src/librustc_middle/ty/fold.rs

-6
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
150150
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
151151
}
152152

153-
/// Does this value contain closures, generators or functions such that it may require
154-
/// polymorphization?
155-
fn may_polymorphize(&self) -> bool {
156-
self.has_type_flags(TypeFlags::MAY_POLYMORPHIZE)
157-
}
158-
159153
/// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
160154
fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
161155
pub struct Visitor<F>(F);

src/librustc_middle/ty/instance.rs

+33-20
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,20 @@ fn polymorphize<'tcx>(
492492
let unused = tcx.unused_generic_params(def_id);
493493
debug!("polymorphize: unused={:?}", unused);
494494

495+
// If this is a closure or generator then we need to handle the case where another closure
496+
// from the function is captured as an upvar and hasn't been polymorphized. In this case,
497+
// the unpolymorphized upvar closure would result in a polymorphized closure producing
498+
// multiple mono items (and eventually symbol clashes).
499+
let upvars_ty = if tcx.is_closure(def_id) {
500+
Some(substs.as_closure().tupled_upvars_ty())
501+
} else if tcx.type_of(def_id).is_generator() {
502+
Some(substs.as_generator().tupled_upvars_ty())
503+
} else {
504+
None
505+
};
506+
let has_upvars = upvars_ty.map(|ty| ty.tuple_fields().count() > 0).unwrap_or(false);
507+
debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
508+
495509
struct PolymorphizationFolder<'tcx> {
496510
tcx: TyCtxt<'tcx>,
497511
};
@@ -512,14 +526,6 @@ fn polymorphize<'tcx>(
512526
self.tcx.mk_closure(def_id, polymorphized_substs)
513527
}
514528
}
515-
ty::FnDef(def_id, substs) => {
516-
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
517-
if substs == polymorphized_substs {
518-
ty
519-
} else {
520-
self.tcx.mk_fn_def(def_id, polymorphized_substs)
521-
}
522-
}
523529
ty::Generator(def_id, substs, movability) => {
524530
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
525531
if substs == polymorphized_substs {
@@ -537,24 +543,31 @@ fn polymorphize<'tcx>(
537543
let is_unused = unused.contains(param.index).unwrap_or(false);
538544
debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
539545
match param.kind {
540-
// If parameter is a const or type parameter..
546+
// Upvar case: If parameter is a type parameter..
547+
ty::GenericParamDefKind::Type { .. } if
548+
// ..and has upvars..
549+
has_upvars &&
550+
// ..and this param has the same type as the tupled upvars..
551+
upvars_ty == Some(substs[param.index as usize].expect_ty()) => {
552+
// ..then double-check that polymorphization marked it used..
553+
debug_assert!(!is_unused);
554+
// ..and polymorphize any closures/generators captured as upvars.
555+
let upvars_ty = upvars_ty.unwrap();
556+
let polymorphized_upvars_ty = upvars_ty.fold_with(
557+
&mut PolymorphizationFolder { tcx });
558+
debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty);
559+
ty::GenericArg::from(polymorphized_upvars_ty)
560+
},
561+
562+
// Simple case: If parameter is a const or type parameter..
541563
ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if
542564
// ..and is within range and unused..
543565
unused.contains(param.index).unwrap_or(false) =>
544566
// ..then use the identity for this parameter.
545567
tcx.mk_param_from_def(param),
546568

547-
// If the parameter does not contain any closures or generators, then use the
548-
// substitution directly.
549-
_ if !substs.may_polymorphize() => substs[param.index as usize],
550-
551-
// Otherwise, use the substitution after polymorphizing.
552-
_ => {
553-
let arg = substs[param.index as usize];
554-
let polymorphized_arg = arg.fold_with(&mut PolymorphizationFolder { tcx });
555-
debug!("polymorphize: arg={:?} polymorphized_arg={:?}", arg, polymorphized_arg);
556-
ty::GenericArg::from(polymorphized_arg)
557-
}
569+
// Otherwise, use the parameter as before.
570+
_ => substs[param.index as usize],
558571
}
559572
})
560573
}

src/librustc_middle/ty/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -575,10 +575,6 @@ bitflags! {
575575
/// Does this value have parameters/placeholders/inference variables which could be
576576
/// replaced later, in a way that would change the results of `impl` specialization?
577577
const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
578-
579-
/// Does this value contain closures, generators or functions such that it may require
580-
/// polymorphization?
581-
const MAY_POLYMORPHIZE = 1 << 18;
582578
}
583579
}
584580

src/test/codegen-units/polymorphization/pr-75255.rs

-52
This file was deleted.

0 commit comments

Comments
 (0)