Skip to content

Commit 6f53ddf

Browse files
committed
Auto merge of #89514 - davidtwco:polymorphize-shims-and-predicates, r=lcnr
polymorphization: shims and predicates Supersedes #75737 and #75414. This pull request includes up some changes to polymorphization which hadn't landed previously and gets stage2 bootstrapping and the test suite passing when polymorphization is enabled. There are still issues with `type_id` and polymorphization to investigate but this should get polymorphization in a reasonable state to work on. - #75737 and #75414 both worked but were blocked on having the rest of the test suite pass (with polymorphization enabled) with and without the PRs. It makes more sense to just land these so that the changes are in. - #75737's changes remove the restriction of `InstanceDef::Item` on polymorphization, so that shims can now be polymorphized. This won't have much of an effect until polymorphization's analysis is more advanced, but it doesn't hurt. - #75414's changes remove all logic which marks parameters as used based on their presence in predicates - given #75675, this will enable more polymorphization and avoid the symbol clashes that predicate logic previously sidestepped. - Polymorphization now explicitly checks (and skips) foreign items, this is necessary for stage2 bootstrapping to work when polymorphization is enabled. - The conditional determining the emission of a note adding context to a post-monomorphization error has been modified. Polymorphization results in `optimized_mir` running for shims during collection where that wouldn't happen previously, some errors are emitted during `optimized_mir` and these were considered post-monomorphization errors with the existing logic (more errors and shims have a `DefId` coming from the std crate, not the local crate), adding a note that resulted in tests failing. It isn't particularly feasible to change where polymorphization runs or prevent it from using `optimized_mir`, so it seemed more reasonable to not change the conditional. - `characteristic_def_id_of_type` was being invoked during partitioning for self types of impl blocks which had projections that depended on the value of unused generic parameters of a function - this caused a ICE in a debuginfo test. If partitioning is enabled and the instance needs substitution then this is skipped. That test still fails for me locally, but not with an ICE, but it fails in a fresh checkout too, so 🤷‍♂️. r? `@lcnr`
2 parents 1d6f242 + b39e915 commit 6f53ddf

File tree

11 files changed

+182
-108
lines changed

11 files changed

+182
-108
lines changed

compiler/rustc_const_eval/src/interpret/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ where
3535
ty::Closure(def_id, substs)
3636
| ty::Generator(def_id, substs, ..)
3737
| ty::FnDef(def_id, substs) => {
38-
let unused_params = self.tcx.unused_generic_params(def_id);
38+
let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
39+
let unused_params = self.tcx.unused_generic_params(instance);
3940
for (index, subst) in substs.into_iter().enumerate() {
4041
let index = index
4142
.try_into()

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ impl IntoArgs for (CrateNum, DefId) {
8383
}
8484
}
8585

86+
impl IntoArgs for ty::InstanceDef<'tcx> {
87+
fn into_args(self) -> (DefId, DefId) {
88+
(self.def_id(), self.def_id())
89+
}
90+
}
91+
8692
provide! { <'tcx> tcx, def_id, other, cdata,
8793
type_of => { cdata.get_type(def_id.index, tcx) }
8894
generics_of => { cdata.get_generics(def_id.index, tcx.sess) }

compiler/rustc_metadata/src/rmeta/encoder.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,9 @@ impl EncodeContext<'a, 'tcx> {
13191319
}
13201320
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
13211321

1322-
let unused = self.tcx.unused_generic_params(def_id);
1322+
let instance =
1323+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
1324+
let unused = self.tcx.unused_generic_params(instance);
13231325
if !unused.is_empty() {
13241326
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
13251327
}

compiler/rustc_middle/src/mir/mono.rs

+8
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ pub enum MonoItem<'tcx> {
4747
}
4848

4949
impl<'tcx> MonoItem<'tcx> {
50+
/// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims).
51+
pub fn is_user_defined(&self) -> bool {
52+
match *self {
53+
MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)),
54+
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true,
55+
}
56+
}
57+
5058
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
5159
match *self {
5260
MonoItem::Fn(instance) => {

compiler/rustc_middle/src/query/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1558,11 +1558,11 @@ rustc_queries! {
15581558
query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
15591559
desc { "codegen_unit" }
15601560
}
1561-
query unused_generic_params(key: DefId) -> FiniteBitSet<u32> {
1562-
cache_on_disk_if { key.is_local() }
1561+
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
1562+
cache_on_disk_if { key.def_id().is_local() }
15631563
desc {
15641564
|tcx| "determining which generic parameters are unused by `{}`",
1565-
tcx.def_path_str(key)
1565+
tcx.def_path_str(key.def_id())
15661566
}
15671567
}
15681568
query backend_optimization_level(_: ()) -> OptLevel {

compiler/rustc_middle/src/ty/instance.rs

+33-12
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@ impl<'tcx> InstanceDef<'tcx> {
152152
}
153153
}
154154

155+
/// Returns the `DefId` of instances which might not require codegen locally.
156+
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
157+
match self {
158+
ty::InstanceDef::Item(def) => Some(def.did),
159+
ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id),
160+
InstanceDef::VtableShim(..)
161+
| InstanceDef::ReifyShim(..)
162+
| InstanceDef::FnPtrShim(..)
163+
| InstanceDef::Virtual(..)
164+
| InstanceDef::Intrinsic(..)
165+
| InstanceDef::ClosureOnceShim { .. }
166+
| InstanceDef::DropGlue(..)
167+
| InstanceDef::CloneShim(..) => None,
168+
}
169+
}
170+
155171
#[inline]
156172
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
157173
match self {
@@ -567,29 +583,26 @@ impl<'tcx> Instance<'tcx> {
567583
return self;
568584
}
569585

570-
if let InstanceDef::Item(def) = self.def {
571-
let polymorphized_substs = polymorphize(tcx, def.did, self.substs);
572-
debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
573-
Self { def: self.def, substs: polymorphized_substs }
574-
} else {
575-
self
576-
}
586+
let polymorphized_substs = polymorphize(tcx, self.def, self.substs);
587+
debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
588+
Self { def: self.def, substs: polymorphized_substs }
577589
}
578590
}
579591

580592
fn polymorphize<'tcx>(
581593
tcx: TyCtxt<'tcx>,
582-
def_id: DefId,
594+
instance: ty::InstanceDef<'tcx>,
583595
substs: SubstsRef<'tcx>,
584596
) -> SubstsRef<'tcx> {
585-
debug!("polymorphize({:?}, {:?})", def_id, substs);
586-
let unused = tcx.unused_generic_params(def_id);
597+
debug!("polymorphize({:?}, {:?})", instance, substs);
598+
let unused = tcx.unused_generic_params(instance);
587599
debug!("polymorphize: unused={:?}", unused);
588600

589601
// If this is a closure or generator then we need to handle the case where another closure
590602
// from the function is captured as an upvar and hasn't been polymorphized. In this case,
591603
// the unpolymorphized upvar closure would result in a polymorphized closure producing
592604
// multiple mono items (and eventually symbol clashes).
605+
let def_id = instance.def_id();
593606
let upvars_ty = if tcx.is_closure(def_id) {
594607
Some(substs.as_closure().tupled_upvars_ty())
595608
} else if tcx.type_of(def_id).is_generator() {
@@ -613,15 +626,23 @@ fn polymorphize<'tcx>(
613626
debug!("fold_ty: ty={:?}", ty);
614627
match ty.kind {
615628
ty::Closure(def_id, substs) => {
616-
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
629+
let polymorphized_substs = polymorphize(
630+
self.tcx,
631+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
632+
substs,
633+
);
617634
if substs == polymorphized_substs {
618635
ty
619636
} else {
620637
self.tcx.mk_closure(def_id, polymorphized_substs)
621638
}
622639
}
623640
ty::Generator(def_id, substs, movability) => {
624-
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
641+
let polymorphized_substs = polymorphize(
642+
self.tcx,
643+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
644+
substs,
645+
);
625646
if substs == polymorphized_substs {
626647
ty
627648
} else {

compiler/rustc_monomorphize/src/collector.rs

+9-15
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,9 @@ fn collect_items_rec<'tcx>(
450450
// involving a dependency, and the lack of context is confusing) in this MVP, we focus on
451451
// diagnostics on edges crossing a crate boundary: the collected mono items which are not
452452
// defined in the local crate.
453-
if tcx.sess.diagnostic().err_count() > error_count && starting_point.node.krate() != LOCAL_CRATE
453+
if tcx.sess.diagnostic().err_count() > error_count
454+
&& starting_point.node.krate() != LOCAL_CRATE
455+
&& starting_point.node.is_user_defined()
454456
{
455457
let formatted_item = with_no_trimmed_paths(|| starting_point.node.to_string());
456458
tcx.sess.span_note_without_error(
@@ -934,21 +936,13 @@ fn visit_instance_use<'tcx>(
934936
}
935937
}
936938

937-
// Returns `true` if we should codegen an instance in the local crate.
938-
// Returns `false` if we can just link to the upstream crate and therefore don't
939-
// need a mono item.
939+
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
940+
/// can just link to the upstream crate and therefore don't need a mono item.
940941
fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
941-
let def_id = match instance.def {
942-
ty::InstanceDef::Item(def) => def.did,
943-
ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
944-
ty::InstanceDef::VtableShim(..)
945-
| ty::InstanceDef::ReifyShim(..)
946-
| ty::InstanceDef::ClosureOnceShim { .. }
947-
| ty::InstanceDef::Virtual(..)
948-
| ty::InstanceDef::FnPtrShim(..)
949-
| ty::InstanceDef::DropGlue(..)
950-
| ty::InstanceDef::Intrinsic(_)
951-
| ty::InstanceDef::CloneShim(..) => return true,
942+
let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() {
943+
def_id
944+
} else {
945+
return true;
952946
};
953947

954948
if tcx.is_foreign_item(def_id) {

compiler/rustc_monomorphize/src/partitioning/default.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
99
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
1010
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
1111
use rustc_middle::ty::print::characteristic_def_id_of_type;
12-
use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
12+
use rustc_middle::ty::{self, fold::TypeFoldable, DefIdTree, InstanceDef, TyCtxt};
1313
use rustc_span::symbol::Symbol;
1414

1515
use super::PartitioningCx;
@@ -300,14 +300,21 @@ fn characteristic_def_id_of_mono_item<'tcx>(
300300
// call it.
301301
return None;
302302
}
303-
// This is a method within an impl, find out what the self-type is:
304-
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
305-
instance.substs,
306-
ty::ParamEnv::reveal_all(),
307-
tcx.type_of(impl_def_id),
308-
);
309-
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
310-
return Some(def_id);
303+
304+
// When polymorphization is enabled, methods which do not depend on their generic
305+
// parameters, but the self-type of their impl block do will fail to normalize.
306+
if !tcx.sess.opts.debugging_opts.polymorphize
307+
|| !instance.definitely_needs_subst(tcx)
308+
{
309+
// This is a method within an impl, find out what the self-type is:
310+
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
311+
instance.substs,
312+
ty::ParamEnv::reveal_all(),
313+
tcx.type_of(impl_def_id),
314+
);
315+
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
316+
return Some(def_id);
317+
}
311318
}
312319
}
313320

0 commit comments

Comments
 (0)