diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index ef0c763ac20..29b3c44dcd6 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -49,6 +49,14 @@ bitflags! { } } +/// Which niches (beyond the `null` niche) are available on references. +#[derive(Default, Copy, Clone, Hash, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +pub struct ReferenceNichePolicy { + pub size: bool, + pub align: bool, +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] pub enum IntegerType { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5c6c3491b38..49bd7b6aa9c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -28,6 +28,7 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::FileName; use rustc_span::SourceFileHashAlgorithm; +use rustc_target::abi::ReferenceNichePolicy; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; @@ -819,6 +820,7 @@ fn test_unstable_options_tracking_hash() { tracked!(profile_emit, Some(PathBuf::from("abc"))); tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); + tracked!(reference_niches, Some(ReferenceNichePolicy { size: true, align: false })); tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a8815ee0908..77c33336dff 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -301,6 +301,7 @@ provide! { tcx, def_id, other, cdata, is_profiler_runtime => { cdata.root.profiler_runtime } required_panic_strategy => { cdata.root.required_panic_strategy } panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy } + reference_niches_policy => { cdata.root.reference_niches_policy } extern_crate => { let r = *cdata.extern_crate.lock(); r.map(|c| &*tcx.arena.alloc(c)) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ac86110f2bd..46571e7796d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -673,6 +673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, + reference_niches_policy: tcx.reference_niches_policy(LOCAL_CRATE), edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 0bc16fc64ff..8bc2e0aa5a9 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -32,7 +32,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span}; -use rustc_target::abi::{FieldIdx, VariantIdx}; +use rustc_target::abi::{FieldIdx, ReferenceNichePolicy, VariantIdx}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; @@ -251,6 +251,7 @@ pub(crate) struct CrateRoot { stable_crate_id: StableCrateId, required_panic_strategy: Option, panic_in_drop_strategy: PanicStrategy, + reference_niches_policy: ReferenceNichePolicy, edition: Edition, has_global_allocator: bool, has_alloc_error_handler: bool, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index a0cb23b5a4c..9bf02267005 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -296,6 +296,7 @@ trivial! { rustc_span::Symbol, rustc_span::symbol::Ident, rustc_target::spec::PanicStrategy, + rustc_target::abi::ReferenceNichePolicy, rustc_type_ir::Variance, u32, usize, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c728cc0b39f..51409f90843 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1480,6 +1480,11 @@ rustc_queries! { desc { "getting a crate's configured panic-in-drop strategy" } separate_provide_extern } + query reference_niches_policy(_: CrateNum) -> abi::ReferenceNichePolicy { + fatal_cycle + desc { "getting a crate's policy for size and alignment niches of references" } + separate_provide_extern + } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle desc { "getting whether a crate has `#![no_builtins]`" } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 593983f117d..43dae9e8de2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3076,6 +3076,7 @@ pub(crate) mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; + use rustc_target::abi::ReferenceNichePolicy; use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -3171,6 +3172,7 @@ pub(crate) mod dep_tracking { OomStrategy, LanguageIdentifier, TraitSolver, + ReferenceNichePolicy, ); impl DepTrackingHash for (T1, T2) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 87d67c099ce..0d63db2bfef 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -6,6 +6,7 @@ use crate::{lint, EarlyErrorHandler}; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::ColorConfig; use rustc_errors::{LanguageIdentifier, TerminalUrl}; +use rustc_target::abi::ReferenceNichePolicy; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -421,6 +422,8 @@ mod desc { pub const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; + pub const parse_opt_reference_niches: &str = + "`null`, or a `,` separated combination of `size` or `align`"; } mod parse { @@ -1253,6 +1256,31 @@ mod parse { }; true } + + pub(crate) fn parse_opt_reference_niches( + slot: &mut Option, + v: Option<&str>, + ) -> bool { + let Some(s) = v else { + return false; + }; + + let slot = slot.get_or_insert_default(); + + if s == "null" { + return true; + } + + for opt in s.split(",") { + match opt { + "size" => slot.size = true, + "align" => slot.align = true, + _ => return false, + } + } + + true + } } options! { @@ -1698,6 +1726,8 @@ options! { "enable queries of the dependency graph for regression testing (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), + reference_niches: Option = (None, parse_opt_reference_niches, [TRACKED], + "override the set of discriminant niches that may be exposed by references"), relax_elf_relocations: Option = (None, parse_opt_bool, [TRACKED], "whether ELF relocations can be relaxed"), relro_level: Option = (None, parse_relro_level, [TRACKED], diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 2afe1cb37bb..19545a1b135 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal}; -use rustc_middle::query::Providers; +use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::layout::{ IntegerExt, LayoutCx, LayoutError, LayoutOf, NaiveLayout, TyAndLayout, TyAndNaiveLayout, MAX_SIMD_LANES, @@ -25,7 +25,14 @@ use crate::errors::{ use crate::layout_sanity_check::sanity_check_layout; pub fn provide(providers: &mut Providers) { - *providers = Providers { layout_of, naive_layout_of, ..*providers }; + *providers = Providers { layout_of, naive_layout_of, reference_niches_policy, ..*providers }; +} + +#[instrument(skip(tcx), level = "debug")] +fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceNichePolicy { + const DEFAULT: ReferenceNichePolicy = ReferenceNichePolicy { size: false, align: false }; + + tcx.sess.opts.unstable_opts.reference_niches.unwrap_or(DEFAULT) } #[instrument(skip(tcx, query), level = "debug")]