diff options
| author | Deadbeef <ent3rm4n@gmail.com> | 2023-09-13 13:55:23 +0000 |
|---|---|---|
| committer | Deadbeef <ent3rm4n@gmail.com> | 2023-09-14 07:34:35 +0000 |
| commit | a0a801cd3807498bdf6b0d7fd4148fdff9ede4b1 (patch) | |
| tree | ebc75e409470028f0151c3c2bd28acde2969c3ae | |
| parent | 7e0261e7ea2085bdc0bc3d0fd6776bf343473858 (diff) | |
| download | rust-a0a801cd3807498bdf6b0d7fd4148fdff9ede4b1.tar.gz rust-a0a801cd3807498bdf6b0d7fd4148fdff9ede4b1.zip | |
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`.
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/callee.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/callee.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/mono.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/diagnostics.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/generic_args.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/generics.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/instance.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/inline.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/collector.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/partitioning.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_symbol_mangling/src/lib.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 1 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_lints/src/derive.rs | 2 |
17 files changed, 71 insertions, 41 deletions
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index a96bd66ba79..9fc77627b1b 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -100,7 +100,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) // whether we are sharing generics or not. The important thing here is // that the visibility we apply to the declaration is the same one that // has been applied to the definition (wherever that definition may be). - let is_generic = instance.args.non_erasable_generics().next().is_some(); + let is_generic = instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some(); if is_generic { // This is a monomorphization. Its expected visibility depends diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 36c098218cf..5254c3f9c9a 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -95,7 +95,8 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage); - let is_generic = instance.args.non_erasable_generics().next().is_some(); + let is_generic = + instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some(); if is_generic { // This is a monomorphization. Its expected visibility depends diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 52481a1090c..c862acdc7de 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -349,6 +349,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { type_names::push_generic_params( tcx, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args), + enclosing_fn_def_id, &mut name, ); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 8fb2ccb7e8a..5b869bed0a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -334,7 +334,7 @@ fn exported_symbols_provider_local( match *mono_item { MonoItem::Fn(Instance { def: InstanceDef::Item(def), args }) => { - if args.non_erasable_generics().next().is_some() { + if args.non_erasable_generics(tcx, def).next().is_some() { let symbol = ExportedSymbol::Generic(def, args); symbols.push(( symbol, @@ -346,10 +346,10 @@ fn exported_symbols_provider_local( )); } } - MonoItem::Fn(Instance { def: InstanceDef::DropGlue(_, Some(ty)), args }) => { + MonoItem::Fn(Instance { def: InstanceDef::DropGlue(def_id, Some(ty)), args }) => { // A little sanity-check debug_assert_eq!( - args.non_erasable_generics().next(), + args.non_erasable_generics(tcx, def_id).next(), Some(GenericArgKind::Type(ty)) ); symbols.push(( diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 067c824aba0..d195e1fc02f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -106,14 +106,14 @@ fn push_debuginfo_type_name<'tcx>( ty_and_layout, &|output, visited| { push_item_name(tcx, def.did(), true, output); - push_generic_params_internal(tcx, args, output, visited); + push_generic_params_internal(tcx, args, def.did(), output, visited); }, output, visited, ); } else { push_item_name(tcx, def.did(), qualified, output); - push_generic_params_internal(tcx, args, output, visited); + push_generic_params_internal(tcx, args, def.did(), output, visited); } } ty::Tuple(component_types) => { @@ -237,8 +237,13 @@ fn push_debuginfo_type_name<'tcx>( let principal = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); push_item_name(tcx, principal.def_id, qualified, output); - let principal_has_generic_params = - push_generic_params_internal(tcx, principal.args, output, visited); + let principal_has_generic_params = push_generic_params_internal( + tcx, + principal.args, + principal.def_id, + output, + visited, + ); let projection_bounds: SmallVec<[_; 4]> = trait_data .projection_bounds() @@ -516,7 +521,13 @@ pub fn compute_debuginfo_vtable_name<'tcx>( tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref); push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); visited.clear(); - push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited); + push_generic_params_internal( + tcx, + trait_ref.args, + trait_ref.def_id, + &mut vtable_name, + &mut visited, + ); } else { vtable_name.push('_'); } @@ -610,20 +621,20 @@ fn push_unqualified_item_name( fn push_generic_params_internal<'tcx>( tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, + def_id: DefId, output: &mut String, visited: &mut FxHashSet<Ty<'tcx>>, ) -> bool { - if args.non_erasable_generics().next().is_none() { + debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); + let mut args = args.non_erasable_generics(tcx, def_id).peekable(); + if args.peek().is_none() { return false; } - - debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); - let cpp_like_debuginfo = cpp_like_debuginfo(tcx); output.push('<'); - for type_parameter in args.non_erasable_generics() { + for type_parameter in args { match type_parameter { GenericArgKind::Type(type_parameter) => { push_debuginfo_type_name(tcx, type_parameter, true, output, visited); @@ -691,11 +702,12 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S pub fn push_generic_params<'tcx>( tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, + def_id: DefId, output: &mut String, ) { let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name"); let mut visited = FxHashSet::default(); - push_generic_params_internal(tcx, args, output, &mut visited); + push_generic_params_internal(tcx, args, def_id, output, &mut visited); } fn push_closure_or_generator_name<'tcx>( @@ -738,7 +750,7 @@ fn push_closure_or_generator_name<'tcx>( // Truncate the args to the length of the above generics. This will cut off // anything closure- or generator-specific. let args = args.truncate_to(tcx, generics); - push_generic_params_internal(tcx, args, output, visited); + push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited); } fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index ac5468f3dfd..6dba5d2945d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1642,8 +1642,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ValuePairs::Terms(infer::ExpectedFound { expected, found }) => { match (expected.unpack(), found.unpack()) { (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { - let is_simple_err = - expected.is_simple_text() && found.is_simple_text(); + let is_simple_err = expected.is_simple_text(self.tcx) + && found.is_simple_text(self.tcx); OpaqueTypesVisitor::visit_expected_found( self.tcx, expected, found, span, ) @@ -1885,7 +1885,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } s }; - if !(values.expected.is_simple_text() && values.found.is_simple_text()) + if !(values.expected.is_simple_text(self.tcx) && values.found.is_simple_text(self.tcx)) || (exp_found.is_some_and(|ef| { // This happens when the type error is a subset of the expectation, // like when you have two references but one is `usize` and the other diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 8fd980d5a9e..403e80bd34c 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -78,9 +78,11 @@ impl<'tcx> MonoItem<'tcx> { } } - pub fn is_generic_fn(&self) -> bool { - match *self { - MonoItem::Fn(ref instance) => instance.args.non_erasable_generics().next().is_some(), + pub fn is_generic_fn(&self, tcx: TyCtxt<'tcx>) -> bool { + match self { + MonoItem::Fn(instance) => { + instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some() + } MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false, } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 5db9b775a0f..e7ebb985ca4 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -70,10 +70,10 @@ impl<'tcx> Ty<'tcx> { /// description in error messages. This is used in the primary span label. Beyond what /// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to /// ADTs with no type arguments. - pub fn is_simple_text(self) -> bool { + pub fn is_simple_text(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { - Adt(_, args) => args.non_erasable_generics().next().is_none(), - Ref(_, ty, _) => ty.is_simple_text(), + Adt(def, args) => args.non_erasable_generics(tcx, def.did()).next().is_none(), + Ref(_, ty, _) => ty.is_simple_text(tcx), _ => self.is_simple_ty(), } } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 153b24acba1..e598ead791e 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -379,12 +379,17 @@ impl<'tcx> GenericArgs<'tcx> { self.iter().filter_map(|k| k.as_const()) } + /// Returns generic arguments that are not lifetimes or host effect params. #[inline] pub fn non_erasable_generics( &'tcx self, + tcx: TyCtxt<'tcx>, + def_id: DefId, ) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx { - self.iter().filter_map(|k| match k.unpack() { - GenericArgKind::Lifetime(_) => None, + let generics = tcx.generics_of(def_id); + self.iter().enumerate().filter_map(|(i, k)| match k.unpack() { + _ if Some(i) == generics.host_effect_index => None, + ty::GenericArgKind::Lifetime(_) => None, generic => Some(generic), }) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index ceac21cf6ea..8e6c1cd4bbb 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -212,10 +212,12 @@ impl<'tcx> Generics { pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { is_host_effect: false, .. } => { return true; } - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { is_host_effect: true, .. } => {} } } false diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 8913bf76d34..e5b9203d12a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -139,7 +139,7 @@ impl<'tcx> Instance<'tcx> { } // If this a non-generic instance, it cannot be a shared monomorphization. - self.args.non_erasable_generics().next()?; + self.args.non_erasable_generics(tcx, self.def_id()).next()?; match self.def { InstanceDef::Item(def) => tcx @@ -344,6 +344,7 @@ impl<'tcx> Instance<'tcx> { pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind { ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + ty::GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(), ty::GenericParamDefKind::Type { .. } => { bug!("Instance::mono: {:?} has type parameters", def_id) } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 7d4c4a823a8..4dc7c3b6444 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -390,7 +390,12 @@ impl<'tcx> Inliner<'tcx> { // Reachability pass defines which functions are eligible for inlining. Generally inlining // other functions is incorrect because they could reference symbols that aren't exported. - let is_generic = callsite.callee.args.non_erasable_generics().next().is_some(); + let is_generic = callsite + .callee + .args + .non_erasable_generics(self.tcx, callsite.callee.def_id()) + .next() + .is_some(); if !is_generic && !callee_attrs.requests_inline() { return Err("not exported"); } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8cbb68fc8c1..026204393ff 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -459,7 +459,7 @@ fn collect_items_rec<'tcx>( // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the // mono item graph. if tcx.sess.diagnostic().err_count() > error_count - && starting_item.node.is_generic_fn() + && starting_item.node.is_generic_fn(tcx) && starting_item.node.is_user_defined() { let formatted_item = with_no_trimmed_paths!(starting_item.node.to_string()); @@ -1315,6 +1315,7 @@ fn create_mono_items_for_default_impls<'tcx>( // it, to validate whether or not the impl is legal to instantiate at all. let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(), GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { unreachable!( "`own_requires_monomorphization` check means that \ diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index de6db8ae6ae..c993e64477b 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -221,7 +221,7 @@ where } let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item); - let is_volatile = is_incremental_build && mono_item.is_generic_fn(); + let is_volatile = is_incremental_build && mono_item.is_generic_fn(cx.tcx); let cgu_name = match characteristic_def_id { Some(def_id) => compute_codegen_unit_name( @@ -801,7 +801,7 @@ fn mono_item_visibility<'tcx>( return Visibility::Hidden; } - let is_generic = instance.args.non_erasable_generics().next().is_some(); + let is_generic = instance.args.non_erasable_generics(tcx, def_id).next().is_some(); // Upstream `DefId` instances get different handling than local ones. let Some(def_id) = def_id.as_local() else { diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 74538e9f5a3..535a3ea2d7e 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -108,7 +108,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::query::Providers; -use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::SymbolManglingVersion; @@ -144,7 +143,7 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty // This closure determines the instantiating crate for instances that // need an instantiating-crate-suffix for their symbol name, in order // to differentiate between local copies. - if is_generic(instance.args) { + if is_generic(instance, tcx) { // For generics we might find re-usable upstream instances. If there // is one, we rely on the symbol being instantiated locally. instance.upstream_monomorphization(tcx).unwrap_or(LOCAL_CRATE) @@ -246,7 +245,7 @@ fn compute_symbol_name<'tcx>( // the ID of the instantiating crate. This avoids symbol conflicts // in case the same instances is emitted in two crates of the same // project. - let avoid_cross_crate_conflicts = is_generic(args) || is_globally_shared_function; + let avoid_cross_crate_conflicts = is_generic(instance, tcx) || is_globally_shared_function; let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate); @@ -278,6 +277,6 @@ fn compute_symbol_name<'tcx>( symbol } -fn is_generic(args: GenericArgsRef<'_>) -> bool { - args.non_erasable_generics().next().is_some() +fn is_generic<'tcx>(instance: Instance<'tcx>, tcx: TyCtxt<'tcx>) -> bool { + instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some() } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index e1a15b5cf9f..da2958bf56e 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -55,6 +55,7 @@ fn resolve_instance<'tcx>( } } else { debug!(" => free item"); + // FIXME(effects): we may want to erase the effect param if that is present on this item. ty::InstanceDef::Item(def_id) }; diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index d3311792cfa..2bdac1352dc 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -343,7 +343,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h // If the current self type doesn't implement Copy (due to generic constraints), search to see if // there's a Copy impl for any instance of the adt. if !is_copy(cx, ty) { - if ty_subs.non_erasable_generics().next().is_some() { + if ty_subs.non_erasable_generics(cx.tcx, ty_adt.did()).next().is_some() { let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| { impls.iter().any(|&id| { matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) |
