Skip to content

Commit 953cfd1

Browse files
committed
treat host effect params as erased generics in codegen
This fixes the changes brought to codegen tests when effect params are added to libcore, by not attempting to monomorphize functions that get the host param by being `const fn`.
1 parent 7e0261e commit 953cfd1

File tree

14 files changed

+63
-26
lines changed

14 files changed

+63
-26
lines changed

Diff for: compiler/rustc_codegen_gcc/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
100100
// whether we are sharing generics or not. The important thing here is
101101
// that the visibility we apply to the declaration is the same one that
102102
// has been applied to the definition (wherever that definition may be).
103-
let is_generic = instance.args.non_erasable_generics().next().is_some();
103+
let is_generic = instance.non_erasable_generics(tcx).next().is_some();
104104

105105
if is_generic {
106106
// This is a monomorphization. Its expected visibility depends

Diff for: compiler/rustc_codegen_llvm/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
9595
unsafe {
9696
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
9797

98-
let is_generic = instance.args.non_erasable_generics().next().is_some();
98+
let is_generic = instance.non_erasable_generics(tcx).next().is_some();
9999

100100
if is_generic {
101101
// This is a monomorphization. Its expected visibility depends

Diff for: compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
349349
type_names::push_generic_params(
350350
tcx,
351351
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
352+
generics,
352353
&mut name,
353354
);
354355

Diff for: compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,8 @@ fn exported_symbols_provider_local(
333333
}
334334

335335
match *mono_item {
336-
MonoItem::Fn(Instance { def: InstanceDef::Item(def), args }) => {
337-
if args.non_erasable_generics().next().is_some() {
336+
MonoItem::Fn(instance @ Instance { def: InstanceDef::Item(def), args }) => {
337+
if instance.non_erasable_generics(tcx).next().is_some() {
338338
let symbol = ExportedSymbol::Generic(def, args);
339339
symbols.push((
340340
symbol,

Diff for: compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -607,23 +607,21 @@ fn push_unqualified_item_name(
607607
};
608608
}
609609

610-
fn push_generic_params_internal<'tcx>(
610+
fn push_generic_params_inner<'tcx>(
611611
tcx: TyCtxt<'tcx>,
612-
args: GenericArgsRef<'tcx>,
612+
args: impl Iterator<Item = GenericArgKind<'tcx>> + 'tcx,
613613
output: &mut String,
614614
visited: &mut FxHashSet<Ty<'tcx>>,
615615
) -> bool {
616-
if args.non_erasable_generics().next().is_none() {
616+
let mut args = args.peekable();
617+
if args.peek().is_none() {
617618
return false;
618619
}
619-
620-
debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
621-
622620
let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
623621

624622
output.push('<');
625623

626-
for type_parameter in args.non_erasable_generics() {
624+
for type_parameter in args {
627625
match type_parameter {
628626
GenericArgKind::Type(type_parameter) => {
629627
push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
@@ -642,6 +640,16 @@ fn push_generic_params_internal<'tcx>(
642640
true
643641
}
644642

643+
fn push_generic_params_internal<'tcx>(
644+
tcx: TyCtxt<'tcx>,
645+
args: GenericArgsRef<'tcx>,
646+
output: &mut String,
647+
visited: &mut FxHashSet<Ty<'tcx>>,
648+
) -> bool {
649+
debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
650+
push_generic_params_inner(tcx, args.non_erasable_generics(), output, visited)
651+
}
652+
645653
fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut String) {
646654
match ct.kind() {
647655
ty::ConstKind::Param(param) => {
@@ -691,11 +699,12 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
691699
pub fn push_generic_params<'tcx>(
692700
tcx: TyCtxt<'tcx>,
693701
args: GenericArgsRef<'tcx>,
702+
generics: &'tcx ty::Generics,
694703
output: &mut String,
695704
) {
696705
let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
697706
let mut visited = FxHashSet::default();
698-
push_generic_params_internal(tcx, args, output, &mut visited);
707+
push_generic_params_inner(tcx, args.non_erasable_generics_real(generics), output, &mut visited);
699708
}
700709

701710
fn push_closure_or_generator_name<'tcx>(

Diff for: compiler/rustc_middle/src/mir/mono.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ impl<'tcx> MonoItem<'tcx> {
7878
}
7979
}
8080

81-
pub fn is_generic_fn(&self) -> bool {
81+
pub fn is_generic_fn(&self, tcx: TyCtxt<'tcx>) -> bool {
8282
match *self {
83-
MonoItem::Fn(ref instance) => instance.args.non_erasable_generics().next().is_some(),
83+
MonoItem::Fn(ref instance) => instance.non_erasable_generics(tcx).next().is_some(),
8484
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false,
8585
}
8686
}

Diff for: compiler/rustc_middle/src/ty/generic_args.rs

+16
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ impl<'tcx> GenericArgs<'tcx> {
379379
self.iter().filter_map(|k| k.as_const())
380380
}
381381

382+
/// Returns generic arguments that are not lifetimes. Consider using `non_erasable_generics_real`
383+
/// if you have access to the generics declaration that this instance is for.
382384
#[inline]
383385
pub fn non_erasable_generics(
384386
&'tcx self,
@@ -389,6 +391,20 @@ impl<'tcx> GenericArgs<'tcx> {
389391
})
390392
}
391393

394+
/// Returns the "real" set of generic arguments that are not erasable. This considers
395+
/// the host effect param information given by `generics`, which are erased to `true`
396+
/// in runtime.
397+
pub fn non_erasable_generics_real(
398+
&'tcx self,
399+
generics: &'tcx ty::Generics,
400+
) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx {
401+
self.iter().enumerate().filter_map(|(i, k)| match k.unpack() {
402+
_ if Some(i) == generics.host_effect_index => None,
403+
ty::GenericArgKind::Lifetime(_) => None,
404+
generic => Some(generic),
405+
})
406+
}
407+
392408
#[inline]
393409
#[track_caller]
394410
pub fn type_at(&self, i: usize) -> Ty<'tcx> {

Diff for: compiler/rustc_middle/src/ty/generics.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,12 @@ impl<'tcx> Generics {
212212
pub fn own_requires_monomorphization(&self) -> bool {
213213
for param in &self.params {
214214
match param.kind {
215-
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
215+
GenericParamDefKind::Type { .. }
216+
| GenericParamDefKind::Const { is_host_effect: false, .. } => {
216217
return true;
217218
}
218-
GenericParamDefKind::Lifetime => {}
219+
GenericParamDefKind::Lifetime
220+
| GenericParamDefKind::Const { is_host_effect: true, .. } => {}
219221
}
220222
}
221223
false

Diff for: compiler/rustc_middle/src/ty/instance.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ impl<'tcx> Instance<'tcx> {
118118
tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty)
119119
}
120120

121+
pub fn non_erasable_generics(
122+
&self,
123+
tcx: TyCtxt<'tcx>,
124+
) -> impl DoubleEndedIterator<Item = ty::GenericArgKind<'tcx>> + 'tcx {
125+
self.args.non_erasable_generics_real(tcx.generics_of(self.def_id()))
126+
}
127+
121128
/// Finds a crate that contains a monomorphization of this instance that
122129
/// can be linked to from the local crate. A return value of `None` means
123130
/// no upstream crate provides such an exported monomorphization.
@@ -139,7 +146,7 @@ impl<'tcx> Instance<'tcx> {
139146
}
140147

141148
// If this a non-generic instance, it cannot be a shared monomorphization.
142-
self.args.non_erasable_generics().next()?;
149+
self.non_erasable_generics(tcx).next()?;
143150

144151
match self.def {
145152
InstanceDef::Item(def) => tcx
@@ -344,6 +351,7 @@ impl<'tcx> Instance<'tcx> {
344351
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
345352
let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
346353
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
354+
ty::GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
347355
ty::GenericParamDefKind::Type { .. } => {
348356
bug!("Instance::mono: {:?} has type parameters", def_id)
349357
}

Diff for: compiler/rustc_mir_transform/src/inline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ impl<'tcx> Inliner<'tcx> {
390390

391391
// Reachability pass defines which functions are eligible for inlining. Generally inlining
392392
// other functions is incorrect because they could reference symbols that aren't exported.
393-
let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();
393+
let is_generic = callsite.callee.non_erasable_generics(self.tcx).next().is_some();
394394
if !is_generic && !callee_attrs.requests_inline() {
395395
return Err("not exported");
396396
}

Diff for: compiler/rustc_monomorphize/src/collector.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ fn collect_items_rec<'tcx>(
459459
// Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the
460460
// mono item graph.
461461
if tcx.sess.diagnostic().err_count() > error_count
462-
&& starting_item.node.is_generic_fn()
462+
&& starting_item.node.is_generic_fn(tcx)
463463
&& starting_item.node.is_user_defined()
464464
{
465465
let formatted_item = with_no_trimmed_paths!(starting_item.node.to_string());
@@ -1315,6 +1315,7 @@ fn create_mono_items_for_default_impls<'tcx>(
13151315
// it, to validate whether or not the impl is legal to instantiate at all.
13161316
let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
13171317
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
1318+
GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
13181319
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
13191320
unreachable!(
13201321
"`own_requires_monomorphization` check means that \

Diff for: compiler/rustc_monomorphize/src/partitioning.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ where
221221
}
222222

223223
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
224-
let is_volatile = is_incremental_build && mono_item.is_generic_fn();
224+
let is_volatile = is_incremental_build && mono_item.is_generic_fn(cx.tcx);
225225

226226
let cgu_name = match characteristic_def_id {
227227
Some(def_id) => compute_codegen_unit_name(
@@ -801,7 +801,7 @@ fn mono_item_visibility<'tcx>(
801801
return Visibility::Hidden;
802802
}
803803

804-
let is_generic = instance.args.non_erasable_generics().next().is_some();
804+
let is_generic = instance.non_erasable_generics(tcx).next().is_some();
805805

806806
// Upstream `DefId` instances get different handling than local ones.
807807
let Some(def_id) = def_id.as_local() else {

Diff for: compiler/rustc_symbol_mangling/src/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
108108
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
109109
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
110110
use rustc_middle::query::Providers;
111-
use rustc_middle::ty::GenericArgsRef;
112111
use rustc_middle::ty::{self, Instance, TyCtxt};
113112
use rustc_session::config::SymbolManglingVersion;
114113

@@ -144,7 +143,7 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty
144143
// This closure determines the instantiating crate for instances that
145144
// need an instantiating-crate-suffix for their symbol name, in order
146145
// to differentiate between local copies.
147-
if is_generic(instance.args) {
146+
if is_generic(instance, tcx) {
148147
// For generics we might find re-usable upstream instances. If there
149148
// is one, we rely on the symbol being instantiated locally.
150149
instance.upstream_monomorphization(tcx).unwrap_or(LOCAL_CRATE)
@@ -246,7 +245,7 @@ fn compute_symbol_name<'tcx>(
246245
// the ID of the instantiating crate. This avoids symbol conflicts
247246
// in case the same instances is emitted in two crates of the same
248247
// project.
249-
let avoid_cross_crate_conflicts = is_generic(args) || is_globally_shared_function;
248+
let avoid_cross_crate_conflicts = is_generic(instance, tcx) || is_globally_shared_function;
250249

251250
let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate);
252251

@@ -278,6 +277,6 @@ fn compute_symbol_name<'tcx>(
278277
symbol
279278
}
280279

281-
fn is_generic(args: GenericArgsRef<'_>) -> bool {
282-
args.non_erasable_generics().next().is_some()
280+
fn is_generic<'tcx>(instance: Instance<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
281+
instance.non_erasable_generics(tcx).next().is_some()
283282
}

Diff for: compiler/rustc_ty_utils/src/instance.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn resolve_instance<'tcx>(
5555
}
5656
} else {
5757
debug!(" => free item");
58+
// FIXME(effects): we may want to erase the effect param if that is present on this item.
5859
ty::InstanceDef::Item(def_id)
5960
};
6061

0 commit comments

Comments
 (0)