From 2445dd794e4e24d62ab8d79ba8924baba44865ae Mon Sep 17 00:00:00 2001 From: kulst Date: Sun, 9 Feb 2025 11:50:06 +0100 Subject: [PATCH 01/25] Persist target features used for codegen beyond tcx Bitcode linkers like llvm-bitcode-linker or bpf linker hand over the target features to llvm during link stage. During link stage the `TyCtxt` is already gone so it is not possible to create a query for the global backend features any longer. The features preserved in `Session.target_features` only incorporate target features known to rustc. This would contradict with the behaviour during codegen stage which also passes target features to llvm which are unknown to rustc. This commit adds target features as a field to the `CrateInfo` struct and queries the target features in its new function. This way the target features are preserved beyond tcx and available at link stage. To make sure the `global_backend_features` query is always registered even if the CodegenBackend does not register it, this registration is added to the `provide`function of the `rustc_codegen_ssa` crate. --- compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_codegen_ssa/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index e800492dad02f..0b420fcfaae26 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -921,6 +921,7 @@ impl CrateInfo { let n_crates = crates.len(); let mut info = CrateInfo { target_cpu, + target_features: tcx.global_backend_features(()).clone(), crate_types, exported_symbols, linked_symbols, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 428a45975f1ec..9d2ac219d592c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -190,6 +190,7 @@ impl From<&cstore::NativeLib> for NativeLib { #[derive(Debug, Encodable, Decodable)] pub struct CrateInfo { pub target_cpu: String, + pub target_features: Vec, pub crate_types: Vec, pub exported_symbols: UnordMap>, pub linked_symbols: FxIndexMap>, @@ -230,6 +231,7 @@ pub fn provide(providers: &mut Providers) { crate::base::provide(providers); crate::target_features::provide(providers); crate::codegen_attrs::provide(providers); + providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![]; } /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc` From 831d9f39e9c330934b7c4f35010477ba4a738d96 Mon Sep 17 00:00:00 2001 From: kulst Date: Wed, 5 Feb 2025 21:33:58 +0100 Subject: [PATCH 02/25] Pass through of target features to llvm-bitcode-linker and handling them The .ptx version produced by llc can be specified by passing it with --mattr. Currently it is not possible to specify the .ptx version with -Ctarget-feature because these are not passed through to llvm-bitcode-linker and handled by it. This commit adds both. --target-feature and -mattr are passed with equals to mitigate issues when the value starts with a - (minus). --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 ++++++ .../src/bin/llvm-bitcode-linker.rs | 6 +++++- src/tools/llvm-bitcode-linker/src/linker.rs | 13 ++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0d1..dceef52e81a2f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2518,6 +2518,12 @@ fn add_order_independent_options( "--target-cpu", &codegen_results.crate_info.target_cpu, ]); + if codegen_results.crate_info.target_features.len() > 0 { + cmd.link_arg(&format!( + "--target-feature={}", + &codegen_results.crate_info.target_features.join(",") + )); + } } else if flavor == LinkerFlavor::Ptx { cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]); } else if flavor == LinkerFlavor::Bpf { diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs index fdbf6171c53f2..608c6605304f4 100644 --- a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs +++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs @@ -27,6 +27,10 @@ pub struct Args { #[arg(long)] target_cpu: Option, + /// The target features + #[arg(long)] + target_feature: Option, + /// Write output to the filename #[arg(short, long)] output: PathBuf, @@ -49,7 +53,7 @@ fn main() -> anyhow::Result<()> { let args = Args::parse(); - let mut linker = Session::new(args.target, args.target_cpu, args.output); + let mut linker = Session::new(args.target, args.target_cpu, args.target_feature, args.output); linker.add_exported_symbols(args.export_symbol); diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs index 9f579d1009408..dafd847e76808 100644 --- a/src/tools/llvm-bitcode-linker/src/linker.rs +++ b/src/tools/llvm-bitcode-linker/src/linker.rs @@ -8,6 +8,7 @@ use crate::{Optimization, Target}; pub struct Session { target: Target, cpu: Option, + feature: Option, symbols: Vec, /// A file that `llvm-link` supports, like a bitcode file or an archive. @@ -21,7 +22,12 @@ pub struct Session { } impl Session { - pub fn new(target: crate::Target, cpu: Option, out_path: PathBuf) -> Self { + pub fn new( + target: crate::Target, + cpu: Option, + feature: Option, + out_path: PathBuf, + ) -> Self { let link_path = out_path.with_extension("o"); let opt_path = out_path.with_extension("optimized.o"); let sym_path = out_path.with_extension("symbols.txt"); @@ -29,6 +35,7 @@ impl Session { Session { target, cpu, + feature, symbols: Vec::new(), files: Vec::new(), link_path, @@ -134,6 +141,10 @@ impl Session { lcc_command.arg("--mcpu").arg(mcpu); } + if let Some(mattr) = &self.feature { + lcc_command.arg(&format!("--mattr={}", mattr)); + } + let lcc_output = lcc_command .arg(&self.opt_path) .arg("-o").arg(&self.out_path) From 40ecda6a33bdfb4ca66ecb5555473511a9b1b9f6 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 17 Feb 2025 21:17:05 +0000 Subject: [PATCH 03/25] Remove obsolete MinGW ThinLTO+TLS workaround #109797 is fixed --- library/std/src/sys/thread_local/os.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 00d2e30bd6036..fe6af27db3a17 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -28,9 +28,7 @@ pub macro thread_local_inner { // user provided type or type alias with a matching name. Please update the shadowing test // in `tests/thread.rs` if these types are renamed. unsafe { - // Inlining does not work on windows-gnu due to linking errors around - // dllimports. See https://github.com/rust-lang/rust/issues/109797. - $crate::thread::LocalKey::new(#[cfg_attr(windows, inline(never))] |init| { + $crate::thread::LocalKey::new(|init| { static VAL: $crate::thread::local_impl::Storage<$t> = $crate::thread::local_impl::Storage::new(); VAL.get(init, __init) From 35febd7a6d57179f41cb5b4a37f9545915e4d7a5 Mon Sep 17 00:00:00 2001 From: Li Keqing Date: Wed, 19 Feb 2025 18:05:37 +0800 Subject: [PATCH 04/25] Fix `*-win7-windows-msvc` target since 26eeac1a1e9fe46ffd80dd0d3dafdd2c2a644306 --- library/std/src/sys/pal/windows/c.rs | 4 ++-- library/std/src/sys/random/windows.rs | 2 +- library/std/src/sys/sync/mutex/windows7.rs | 2 +- library/std/src/sys/sync/thread_parking/windows7.rs | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 8dc61edb603f4..4fbdc839939c9 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -204,7 +204,7 @@ compat_fn_with_fallback! { pub fn NtReleaseKeyedEvent( EventHandle: HANDLE, Key: *const c_void, - Alertable: BOOLEAN, + Alertable: bool, Timeout: *mut i64 ) -> NTSTATUS { panic!("keyed events not available") @@ -213,7 +213,7 @@ compat_fn_with_fallback! { pub fn NtWaitForKeyedEvent( EventHandle: HANDLE, Key: *const c_void, - Alertable: BOOLEAN, + Alertable: bool, Timeout: *mut i64 ) -> NTSTATUS { panic!("keyed events not available") diff --git a/library/std/src/sys/random/windows.rs b/library/std/src/sys/random/windows.rs index 7566000f9e6ff..f5da637f56ca9 100644 --- a/library/std/src/sys/random/windows.rs +++ b/library/std/src/sys/random/windows.rs @@ -14,7 +14,7 @@ pub fn fill_bytes(mut bytes: &mut [u8]) { while !bytes.is_empty() { let len = bytes.len().try_into().unwrap_or(u32::MAX); let ret = unsafe { c::RtlGenRandom(bytes.as_mut_ptr().cast(), len) }; - assert_ne!(ret, 0, "failed to generate random data"); + assert!(ret, "failed to generate random data"); bytes = &mut bytes[len as usize..]; } } diff --git a/library/std/src/sys/sync/mutex/windows7.rs b/library/std/src/sys/sync/mutex/windows7.rs index 689dba10f01ed..0b57de78ba6dd 100644 --- a/library/std/src/sys/sync/mutex/windows7.rs +++ b/library/std/src/sys/sync/mutex/windows7.rs @@ -44,7 +44,7 @@ impl Mutex { #[inline] pub fn try_lock(&self) -> bool { - unsafe { c::TryAcquireSRWLockExclusive(raw(self)) != 0 } + unsafe { c::TryAcquireSRWLockExclusive(raw(self)) } } #[inline] diff --git a/library/std/src/sys/sync/thread_parking/windows7.rs b/library/std/src/sys/sync/thread_parking/windows7.rs index f7585e882f055..a1a0f8427cd83 100644 --- a/library/std/src/sys/sync/thread_parking/windows7.rs +++ b/library/std/src/sys/sync/thread_parking/windows7.rs @@ -195,7 +195,7 @@ mod keyed_events { pub unsafe fn park(parker: Pin<&Parker>) { // Wait for unpark() to produce this event. - c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut()); + c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut()); // Set the state back to EMPTY (from either PARKED or NOTIFIED). // Note that we don't just write EMPTY, but use swap() to also // include an acquire-ordered read to synchronize with unpark()'s @@ -218,7 +218,7 @@ mod keyed_events { // Wait for unpark() to produce this event. let unparked = - c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS; + c::NtWaitForKeyedEvent(handle, parker.ptr(), false, &mut timeout) == c::STATUS_SUCCESS; // Set the state back to EMPTY (from either PARKED or NOTIFIED). let prev_state = parker.state.swap(EMPTY, Acquire); @@ -228,7 +228,7 @@ mod keyed_events { // was set to NOTIFIED, which means we *just* missed an // unpark(), which is now blocked on us to wait for it. // Wait for it to consume the event and unblock that thread. - c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, ptr::null_mut()); + c::NtWaitForKeyedEvent(handle, parker.ptr(), false, ptr::null_mut()); } } pub unsafe fn unpark(parker: Pin<&Parker>) { @@ -239,7 +239,7 @@ mod keyed_events { // To prevent this thread from blocking indefinitely in that case, // park_impl() will, after seeing the state set to NOTIFIED after // waking up, call NtWaitForKeyedEvent again to unblock us. - c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut()); + c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut()); } fn keyed_event_handle() -> c::HANDLE { From 78ddabf31d3147a19be77c3b38b49fe60915d75a Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Sun, 13 Oct 2024 14:58:44 +0200 Subject: [PATCH 05/25] Create a generic AVR target: avr-none This commit removes the `avr-unknown-gnu-atmega328` target and replaces it with a more generic `avr-none` variant that must be specialized with the `-C target-cpu` flag (e.g. `-C target-cpu=atmega328p`). --- compiler/rustc_codegen_ssa/src/back/link.rs | 1 + compiler/rustc_codegen_ssa/src/back/linker.rs | 12 +++ .../src/spec/base/{avr_gnu.rs => avr.rs} | 40 --------- compiler/rustc_target/src/spec/base/mod.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 9 ++- .../rustc_target/src/spec/targets/avr_none.rs | 32 ++++++++ .../spec/targets/avr_unknown_gnu_atmega328.rs | 5 -- src/doc/rustc/src/platform-support.md | 2 +- .../rustc/src/platform-support/avr-none.md | 81 +++++++++++++++++++ src/tools/compiletest/src/header/tests.rs | 3 + .../src/external_deps/rustc.rs | 7 ++ tests/assembly/asm/avr-modifiers.rs | 2 +- tests/assembly/asm/avr-types.rs | 2 +- tests/assembly/targets/targets-pe.rs | 6 +- tests/codegen/asm/avr-clobbers.rs | 2 +- tests/codegen/avr/avr-func-addrspace.rs | 2 +- tests/run-make/avr-rjmp-offset/rmake.rs | 4 +- .../feature-gate-abi-avr-interrupt.rs | 2 +- tests/ui/repr/16-bit-repr-c-enum.rs | 2 +- 19 files changed, 156 insertions(+), 60 deletions(-) rename compiler/rustc_target/src/spec/base/{avr_gnu.rs => avr.rs} (91%) create mode 100644 compiler/rustc_target/src/spec/targets/avr_none.rs delete mode 100644 compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs create mode 100644 src/doc/rustc/src/platform-support/avr-none.md diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0d1..0399ea77c72af 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1990,6 +1990,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) if let Some(args) = sess.target.pre_link_args.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); } + cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e3ace01c1eb54..8900405c1b8f8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -153,6 +153,7 @@ pub(crate) fn get_linker<'a>( hinted_static: None, is_ld: cc == Cc::No, is_gnu: flavor.is_gnu(), + uses_lld: flavor.uses_lld(), }) as Box, LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box, LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box, @@ -361,6 +362,7 @@ struct GccLinker<'a> { // Link as ld is_ld: bool, is_gnu: bool, + uses_lld: bool, } impl<'a> GccLinker<'a> { @@ -552,6 +554,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_args(&["--entry", "_initialize"]); } } + // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc, // it switches linking for libc and similar system libraries to static without using // any `#[link]` attributes in the `libc` crate, see #72782 for details. @@ -567,6 +570,15 @@ impl<'a> Linker for GccLinker<'a> { { self.cc_arg("--static-crt"); } + + // avr-none doesn't have default ISA, users must specify which specific + // CPU (well, microcontroller) they are targetting using `-Ctarget-cpu`. + // + // Currently this makes sense only when using avr-gcc as a linker, since + // it brings a couple of hand-written important intrinsics from libgcc. + if self.sess.target.arch == "avr" && !self.uses_lld { + self.verbatim_arg(format!("-mmcu={}", self.target_cpu)); + } } fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) { diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr.rs similarity index 91% rename from compiler/rustc_target/src/spec/base/avr_gnu.rs rename to compiler/rustc_target/src/spec/base/avr.rs index 3554dcfcb4a13..85b73e61e52cd 100644 --- a/compiler/rustc_target/src/spec/base/avr_gnu.rs +++ b/compiler/rustc_target/src/spec/base/avr.rs @@ -1,45 +1,5 @@ use object::elf; -use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions}; - -/// A base target for AVR devices using the GNU toolchain. -/// -/// Requires GNU avr-gcc and avr-binutils on the host system. -/// FIXME: Remove the second parameter when const string concatenation is possible. -pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { - Target { - arch: "avr".into(), - metadata: crate::spec::TargetMetadata { - description: None, - tier: None, - host_tools: None, - std: None, - }, - data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), - llvm_target: "avr-unknown-unknown".into(), - pointer_width: 16, - options: TargetOptions { - env: "gnu".into(), - - c_int_width: "16".into(), - cpu: target_cpu.into(), - exe_suffix: ".elf".into(), - - linker: Some("avr-gcc".into()), - eh_frame_header: false, - pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]), - late_link_args: TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-lgcc"], - ), - max_atomic_width: Some(16), - atomic_cas: false, - relocation_model: RelocModel::Static, - ..TargetOptions::default() - }, - } -} - /// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the /// name of the target CPU / MCU. /// diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index b9139c8452c5f..6f88be5d37f16 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -1,7 +1,7 @@ pub(crate) mod aix; pub(crate) mod android; pub(crate) mod apple; -pub(crate) mod avr_gnu; +pub(crate) mod avr; pub(crate) mod bpf; pub(crate) mod cygwin; pub(crate) mod dragonfly; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f7e467b0c1155..3b943fc178f27 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,7 +60,7 @@ pub mod crt_objects; mod base; mod json; -pub use base::avr_gnu::ef_avr_arch; +pub use base::avr::ef_avr_arch; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -1797,7 +1797,7 @@ supported_targets! { ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia), ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia), - ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328), + ("avr-none", avr_none), ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc), @@ -3062,7 +3062,10 @@ impl Target { &self.post_link_args, ] { for (&flavor, flavor_args) in args { - check!(!flavor_args.is_empty(), "linker flavor args must not be empty"); + check!( + !flavor_args.is_empty() || self.arch == "avr", + "linker flavor args must not be empty" + ); // Check that flavors mentioned in link args are compatible with the default flavor. match self.linker_flavor { LinkerFlavor::Gnu(..) => { diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs new file mode 100644 index 0000000000000..91d3197d0998e --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/avr_none.rs @@ -0,0 +1,32 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + arch: "avr".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: None, + host_tools: None, + std: None, + }, + data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), + llvm_target: "avr-unknown-unknown".into(), + pointer_width: 16, + options: TargetOptions { + c_int_width: "16".into(), + exe_suffix: ".elf".into(), + linker: Some("avr-gcc".into()), + eh_frame_header: false, + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[]), + late_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-lgcc"], + ), + max_atomic_width: Some(16), + atomic_cas: false, + relocation_model: RelocModel::Static, + need_explicit_cpu: true, + ..TargetOptions::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs deleted file mode 100644 index c3d6fb722733d..0000000000000 --- a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::{Target, base}; - -pub(crate) fn target() -> Target { - base::avr_gnu::target("atmega328", "-mmcu=atmega328") -} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index b5cd3864620d3..c7f4ab48ab13e 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -301,7 +301,7 @@ target | std | host | notes [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat [`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX [`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat -`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` +`avr-none` | * | | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) `csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian) diff --git a/src/doc/rustc/src/platform-support/avr-none.md b/src/doc/rustc/src/platform-support/avr-none.md new file mode 100644 index 0000000000000..9c1836222c103 --- /dev/null +++ b/src/doc/rustc/src/platform-support/avr-none.md @@ -0,0 +1,81 @@ +# `avr-none` + +Series of microcontrollers from Atmel: ATmega8, ATmega328p etc. + +**Tier: 3** + +## Target maintainers + +- [Patryk Wychowaniec](https://github.com/Patryk27) + +## Requirements + +This target is only cross-compiled; x86-64 Linux, x86-64 macOS and aarch64 macOS +hosts are confirmed to work, but in principle any machine able to run rustc and +avr-gcc should be good. + +Compiling for this target requires `avr-gcc` installed, because a couple of +intrinsics (like 32-bit multiplication) rely on [`libgcc`](https://github.com/gcc-mirror/gcc/blob/3269a722b7a03613e9c4e2862bc5088c4a17cc11/libgcc/config/avr/lib1funcs.S) +and can't be provided through `compiler-builtins` yet. This is a limitation that +[we hope to lift in the future](https://github.com/rust-lang/compiler-builtins/issues/711). + +You'll also need to setup the `.cargo/config` file - see below for details. + +## Building the target + +Rust comes with AVR support enabled, you don't have to rebuild the compiler. + +## Building Rust programs + +Install `avr-gcc`: + +```console +# Ubuntu: +$ sudo apt-get install gcc-avr + +# Mac: +$ brew tap osx-cross/avr && brew install avr-gcc + +# NixOS (takes a couple of minutes, since it's not provided through Hydra): +$ nix shell nixpkgs#pkgsCross.avr.buildPackages.gcc11 +``` + +... setup `.cargo/config` for your project: + +```toml +[build] +target = "avr-none" +rustflags = ["-C", "target-cpu=atmega328p"] + +[unstable] +build-std = ["core"] +``` + +... and then simply run: + +```console +$ cargo build --release +``` + +The final binary will be placed into +`./target/avr-none/release/your-project.elf`. + +Note that since AVRs have rather small amounts of registers, ROM and RAM, it's +recommended to always use `--release` to avoid running out of space. + +Also, please note that specifying `-C target-cpu` is required - here's a list of +the possible variants: + +https://github.com/llvm/llvm-project/blob/093d4db2f3c874d4683fb01194b00dbb20e5c713/clang/lib/Basic/Targets/AVR.cpp#L32 + +## Testing + +You can use [`simavr`](https://github.com/buserror/simavr) to emulate the +resulting firmware on your machine: + +```console +$ simavr -m atmega328p ./target/avr-none/release/your-project.elf +``` + +Alternatively, if you want to write a couple of actual `#[test]`s, you can use +[`avr-tester`](https://github.com/Patryk27/avr-tester). diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 55292c46bba9c..c65f10a52bd5b 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -465,7 +465,10 @@ fn profiler_runtime() { #[test] fn asm_support() { let asms = [ + #[cfg(bootstrap)] ("avr-unknown-gnu-atmega328", false), + #[cfg(not(bootstrap))] + ("avr-none", false), ("i686-unknown-netbsd", true), ("riscv32gc-unknown-linux-gnu", true), ("riscv64imac-unknown-none-elf", true), diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index fd4a20278addd..710ba025830a8 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -253,6 +253,13 @@ impl Rustc { self } + /// Specify the target CPU. + pub fn target_cpu>(&mut self, target_cpu: S) -> &mut Self { + let target_cpu = target_cpu.as_ref(); + self.cmd.arg(format!("-Ctarget-cpu={target_cpu}")); + self + } + /// Specify the crate type. pub fn crate_type(&mut self, crate_type: &str) -> &mut Self { self.cmd.arg("--crate-type"); diff --git a/tests/assembly/asm/avr-modifiers.rs b/tests/assembly/asm/avr-modifiers.rs index 585fdd7b72534..124cad9bef6a8 100644 --- a/tests/assembly/asm/avr-modifiers.rs +++ b/tests/assembly/asm/avr-modifiers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![feature(no_core, asm_experimental_arch)] diff --git a/tests/assembly/asm/avr-types.rs b/tests/assembly/asm/avr-types.rs index 25cf3ec3b4bde..309405f4d51e7 100644 --- a/tests/assembly/asm/avr-types.rs +++ b/tests/assembly/asm/avr-types.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![feature(no_core, asm_experimental_arch)] diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs index 1fa4dc821dd37..b74d0181c4d67 100644 --- a/tests/assembly/targets/targets-pe.rs +++ b/tests/assembly/targets/targets-pe.rs @@ -15,9 +15,9 @@ //@ revisions: arm64ec_pc_windows_msvc //@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64 -//@ revisions: avr_unknown_gnu_atmega328 -//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 -//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr +//@ revisions: avr_none +//@ [avr_none] compile-flags: --target avr-none -C target-cpu=atmega328p +//@ [avr_none] needs-llvm-components: avr //@ revisions: bpfeb_unknown_none //@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none //@ [bpfeb_unknown_none] needs-llvm-components: bpf diff --git a/tests/codegen/asm/avr-clobbers.rs b/tests/codegen/asm/avr-clobbers.rs index 56218cd7bcffb..9451127bf04ab 100644 --- a/tests/codegen/asm/avr-clobbers.rs +++ b/tests/codegen/asm/avr-clobbers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![crate_type = "rlib"] diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index ed8acccb1ad85..2ec7c86b5f43c 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Copt-level=3 --target=avr-unknown-gnu-atmega328 --crate-type=rlib -C panic=abort +//@ compile-flags: -Copt-level=3 --target=avr-none -C target-cpu=atmega328p --crate-type=rlib -C panic=abort //@ needs-llvm-components: avr // This test validates that function pointers can be stored in global variables diff --git a/tests/run-make/avr-rjmp-offset/rmake.rs b/tests/run-make/avr-rjmp-offset/rmake.rs index de64b724eed2d..73b6ab3977e97 100644 --- a/tests/run-make/avr-rjmp-offset/rmake.rs +++ b/tests/run-make/avr-rjmp-offset/rmake.rs @@ -22,7 +22,8 @@ fn main() { .input("avr-rjmp-offsets.rs") .opt_level("s") .panic("abort") - .target("avr-unknown-gnu-atmega328") + .target("avr-none") + .target_cpu("avr") // normally one links with `avr-gcc`, but this is not available in CI, // hence this test diverges from the default behavior to enable linking // at all, which is necessary for the test (to resolve the labels). To @@ -49,6 +50,7 @@ fn main() { // of the Rust compiler did produce a label `rjmp .-4` (misses the first // instruction in the loop). assert!(disassembly.contains("
"), "no main function in output"); + disassembly .trim() .lines() diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs index 5386628a8e069..ce3d3fc645d76 100644 --- a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs +++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs @@ -1,5 +1,5 @@ //@ needs-llvm-components: avr -//@ compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +//@ compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib #![no_core] #![feature(no_core, lang_items)] #[lang="sized"] diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2b6bbf1265083..011076882d24f 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -2,7 +2,7 @@ //@ revisions: avr msp430 // //@ [avr] needs-llvm-components: avr -//@ [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib //@ [msp430] needs-llvm-components: msp430 //@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib #![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] From c9fbaab4533f109ce4e7b56ab8d3df0a49c46ffb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 14:16:22 +1100 Subject: [PATCH 06/25] Reflow `MirPhase` comments. Currently many of them exceed 100 chars, which makes them painful to read on a terminal that is 100 chars wide. --- compiler/rustc_middle/src/mir/syntax.rs | 47 +++++++++++++------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 389792a04f8a0..69c19ae7b9c2a 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -53,7 +53,8 @@ pub enum MirPhase { /// sequences of statements that would generally be subject to constant promotion are /// semantically constants, while in analysis MIR all constants are explicit. /// - /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` queries. + /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` + /// queries. /// /// This is the version of MIR used by borrowck and friends. Analysis(AnalysisPhase), @@ -61,26 +62,27 @@ pub enum MirPhase { /// /// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows: /// - /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly speaking, - /// if dataflow analysis determines that the place being dropped is uninitialized, the drop will - /// not be executed. The exact semantics of this aren't written down anywhere, which means they - /// are essentially "what drop elaboration does." In runtime MIR, the drops are unconditional; - /// when a `Drop` terminator is reached, if the type has drop glue that drop glue is always - /// executed. This may be UB if the underlying place is not initialized. - /// - Packed drops: Places might in general be misaligned - in most cases this is UB, the exception - /// is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be misaligned - /// for this reason implicitly moves `P` to a temporary before dropping. Runtime MIR has no such - /// rules, and dropping a misaligned place is simply UB. - /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In runtime - /// MIR, this is UB. - /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way - /// that Rust itself has them. Where exactly these are is generally subject to change, and so we - /// don't document this here. Runtime MIR has most retags explicit (though implicit retags - /// can still occur at `Rvalue::{Ref,AddrOf}`). - /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code has - /// access to. This occurs in coroutine bodies. Such locals do not behave like other locals, - /// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals - - /// all coroutine bodies are lowered and so all places that look like locals really are locals. + /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly + /// speaking, if dataflow analysis determines that the place being dropped is uninitialized, + /// the drop will not be executed. The exact semantics of this aren't written down anywhere, + /// which means they are essentially "what drop elaboration does." In runtime MIR, the drops + /// are unconditional; when a `Drop` terminator is reached, if the type has drop glue that + /// drop glue is always executed. This may be UB if the underlying place is not initialized. + /// - Packed drops: Places might in general be misaligned - in most cases this is UB, the + /// exception is fields of packed structs. In analysis MIR, `Drop(P)` for a `P` that might be + /// misaligned for this reason implicitly moves `P` to a temporary before dropping. Runtime + /// MIR has no such rules, and dropping a misaligned place is simply UB. + /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In + /// runtime MIR, this is UB. + /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same + /// way that Rust itself has them. Where exactly these are is generally subject to change, + /// and so we don't document this here. Runtime MIR has most retags explicit (though implicit + /// retags can still occur at `Rvalue::{Ref,AddrOf}`). + /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code + /// has access to. This occurs in coroutine bodies. Such locals do not behave like other + /// locals, because they eg may be aliased in surprising ways. Runtime MIR has no such + /// special locals. All coroutine bodies are lowered and so all places that look like locals + /// really are locals. /// /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that @@ -111,7 +113,8 @@ pub enum AnalysisPhase { /// * [`TerminatorKind::FalseEdge`] /// * [`StatementKind::FakeRead`] /// * [`StatementKind::AscribeUserType`] - /// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`] + /// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or + /// [`CoverageKind::SpanMarker`] /// * [`Rvalue::Ref`] with `BorrowKind::Fake` /// * [`CastKind::PointerCoercion`] with any of the following: /// * [`PointerCoercion::ArrayToPointer`] From c039533656d344b465cf95da721197a6fdd3d7f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 14:33:59 +1100 Subject: [PATCH 07/25] Improve MIR phase comments. I found the dialect/phase distinction quite confusing when I first read these comments. This commit clarifies things a bit. --- compiler/rustc_middle/src/mir/syntax.rs | 51 ++++++++++++++----------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 69c19ae7b9c2a..b63c4d172f2e7 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -23,44 +23,49 @@ use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex} /// Represents the "flavors" of MIR. /// -/// All flavors of MIR use the same data structure, but there are some important differences. These -/// differences come in two forms: Dialects and phases. +/// The MIR pipeline is structured into a few major dialects, with one or more phases within each +/// dialect. A MIR flavor is identified by a dialect-phase pair. A single `MirPhase` value +/// specifies such a pair. All flavors of MIR use the same data structure to represent the program. /// -/// Dialects represent a stronger distinction than phases. This is because the transitions between -/// dialects are semantic changes, and therefore technically *lowerings* between distinct IRs. In -/// other words, the same [`Body`](crate::mir::Body) might be well-formed for multiple dialects, but -/// have different semantic meaning and different behavior at runtime. +/// Different MIR dialects have different semantics. (The differences between dialects are small, +/// but they do exist.) The progression from one MIR dialect to the next is technically a lowering +/// from one IR to another. In other words, a single well-formed [`Body`](crate::mir::Body) might +/// have different semantic meaning and different behavior at runtime in the different dialects. +/// The specific differences between dialects are described on the variants below. /// -/// Each dialect additionally has a number of phases. However, phase changes never involve semantic -/// changes. If some MIR is well-formed both before and after a phase change, it is also guaranteed -/// that it has the same semantic meaning. In this sense, phase changes can only add additional -/// restrictions on what MIR is well-formed. +/// Phases exist only to place restrictions on what language constructs are permitted in +/// well-formed MIR, and subsequent phases mostly increase those restrictions. I.e. to convert MIR +/// from one phase to the next might require removing/replacing certain MIR constructs. /// -/// When adding phases, remember to update [`MirPhase::phase_index`]. +/// When adding dialects or phases, remember to update [`MirPhase::phase_index`]. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(HashStable)] pub enum MirPhase { - /// The MIR that is generated by MIR building. + /// The "built MIR" dialect, as generated by MIR building. /// /// The only things that operate on this dialect are unsafeck, the various MIR lints, and const /// qualifs. /// - /// This has no distinct phases. + /// This dialect has just the one (implicit) phase, which places few restrictions on what MIR + /// constructs are allowed. Built, - /// The MIR used for most analysis. + + /// The "analysis MIR" dialect, used for borrowck and friends. /// - /// The only semantic change between analysis and built MIR is constant promotion. In built MIR, - /// sequences of statements that would generally be subject to constant promotion are - /// semantically constants, while in analysis MIR all constants are explicit. + /// The only semantic difference between built MIR and analysis MIR relates to constant + /// promotion. In built MIR, sequences of statements that would generally be subject to + /// constant promotion are semantically constants, while in analysis MIR all constants are + /// explicit. /// /// The result of const promotion is available from the `mir_promoted` and `promoted_mir` /// queries. /// - /// This is the version of MIR used by borrowck and friends. + /// The phases of this dialect are described in `AnalysisPhase`. Analysis(AnalysisPhase), - /// The MIR used for CTFE, optimizations, and codegen. + + /// The "runtime MIR" dialect, used for CTFE, optimizations, and codegen. /// - /// The semantic changes that occur in the lowering from analysis to runtime MIR are as follows: + /// The semantic differences between analysis MIR and runtime MIR are as follows. /// /// - Drops: In analysis MIR, `Drop` terminators represent *conditional* drops; roughly /// speaking, if dataflow analysis determines that the place being dropped is uninitialized, @@ -80,13 +85,15 @@ pub enum MirPhase { /// retags can still occur at `Rvalue::{Ref,AddrOf}`). /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code /// has access to. This occurs in coroutine bodies. Such locals do not behave like other - /// locals, because they eg may be aliased in surprising ways. Runtime MIR has no such + /// locals, because they e.g. may be aliased in surprising ways. Runtime MIR has no such /// special locals. All coroutine bodies are lowered and so all places that look like locals /// really are locals. /// /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that - /// transformations which may suppress such errors should not run on analysis MIR. + /// transformations that can suppress such errors should not run on analysis MIR. + /// + /// The phases of this dialect are described in `RuntimePhase`. Runtime(RuntimePhase), } From 83a7fb61fbf2377961d05cad10a699fd954a4bb7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2025 15:17:50 +1100 Subject: [PATCH 08/25] Improve how the MIR dialect/phase index is reported. The only visible change is to the filenames produce by `-Zdump-mir`. E.g. before and after: ``` h.main.003-000.analysis-post-cleanup.after.mir h.main.2-2-000.analysis-post-cleanup.after.mir ``` It also fixes a FIXME comment. --- compiler/rustc_middle/src/mir/mod.rs | 21 +++++++-------------- compiler/rustc_middle/src/mir/pretty.rs | 3 ++- compiler/rustc_middle/src/mir/syntax.rs | 2 +- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 528da4ca05776..096422369dc05 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -99,20 +99,13 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { } impl MirPhase { - /// Gets the index of the current MirPhase within the set of all `MirPhase`s. - /// - /// FIXME(JakobDegen): Return a `(usize, usize)` instead. - pub fn phase_index(&self) -> usize { - const BUILT_PHASE_COUNT: usize = 1; - const ANALYSIS_PHASE_COUNT: usize = 2; - match self { - MirPhase::Built => 1, - MirPhase::Analysis(analysis_phase) => { - 1 + BUILT_PHASE_COUNT + (*analysis_phase as usize) - } - MirPhase::Runtime(runtime_phase) => { - 1 + BUILT_PHASE_COUNT + ANALYSIS_PHASE_COUNT + (*runtime_phase as usize) - } + /// Gets the (dialect, phase) index of the current `MirPhase`. Both numbers + /// are 1-indexed. + pub fn index(&self) -> (usize, usize) { + match *self { + MirPhase::Built => (1, 1), + MirPhase::Analysis(analysis_phase) => (2, 1 + analysis_phase as usize), + MirPhase::Runtime(runtime_phase) => (3, 1 + runtime_phase as usize), } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 1e3b8d029e1b3..dd3de48fc14fd 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -231,7 +231,8 @@ fn dump_path<'tcx>( let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { String::new() } else if pass_num { - format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count) + let (dialect_index, phase_index) = body.phase.index(); + format!(".{}-{}-{:03}", dialect_index, phase_index, body.pass_count) } else { ".-------".to_string() }; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b63c4d172f2e7..af6f0e4c55183 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -37,7 +37,7 @@ use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex} /// well-formed MIR, and subsequent phases mostly increase those restrictions. I.e. to convert MIR /// from one phase to the next might require removing/replacing certain MIR constructs. /// -/// When adding dialects or phases, remember to update [`MirPhase::phase_index`]. +/// When adding dialects or phases, remember to update [`MirPhase::index`]. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(HashStable)] pub enum MirPhase { From a1a8df2a5b0bf5ce07cd93cf641bf060db43e8ef Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Feb 2025 17:11:12 +0000 Subject: [PATCH 09/25] Tweak error code for sized checks of const/static --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 14 +++++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 4 ++-- tests/ui/consts/const-slice-array-deref.stderr | 1 + tests/ui/consts/const-unsized.stderr | 4 ++++ .../consts/const_refs_to_static-ice-121413.stderr | 1 + .../issue-36122-accessing-externed-dst.stderr | 1 + tests/ui/issues/issue-54410.stderr | 1 + tests/ui/static/issue-24446.stderr | 1 + tests/ui/statics/unsized_type2.stderr | 1 + .../ice-unsized-tuple-const-issue-121443.stderr | 1 + 12 files changed, 26 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index edfa897860b7d..a11f025d81ec7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1110,7 +1110,13 @@ fn check_associated_item( let ty = tcx.type_of(item.def_id).instantiate_identity(); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); - check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span)); + check_sized_if_body( + wfcx, + item.def_id.expect_local(), + ty, + Some(span), + ObligationCauseCode::SizedConstOrStatic, + ); Ok(()) } ty::AssocKind::Fn => { @@ -1356,7 +1362,7 @@ fn check_item_type( traits::ObligationCause::new( ty_span, wfcx.body_def_id, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::SizedConstOrStatic, ), wfcx.param_env, item_ty, @@ -1700,6 +1706,7 @@ fn check_fn_or_method<'tcx>( hir::FnRetTy::Return(ty) => Some(ty.span), hir::FnRetTy::DefaultReturn(_) => None, }, + ObligationCauseCode::SizedReturnType, ); } @@ -1708,13 +1715,14 @@ fn check_sized_if_body<'tcx>( def_id: LocalDefId, ty: Ty<'tcx>, maybe_span: Option, + code: ObligationCauseCode<'tcx>, ) { let tcx = wfcx.tcx(); if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) { let span = maybe_span.unwrap_or(body.value.span); wfcx.register_bound( - ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType), + ObligationCause::new(span, def_id, code), wfcx.param_env, ty, tcx.require_lang_item(LangItem::Sized, Some(span)), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1c63b8b365594..c39ed29d0d315 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1810,7 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { crate::GatherLocalsVisitor::new(&fcx).visit_body(body); let ty = fcx.check_expr_with_expectation(body.value, expected); - fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized); + fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic); fcx.write_ty(block.hir_id, ty); ty } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index f039da772fd4d..673751b7e100d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -273,7 +273,7 @@ pub enum ObligationCauseCode<'tcx> { }, /// Constant expressions must be sized. - ConstSized, + SizedConstOrStatic, /// `static` items must have `Sync` type. SharedStatic, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ee0ab0dfbb82a..2de005ef0192d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3125,8 +3125,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - ObligationCauseCode::ConstSized => { - err.note("constant expressions must have a statically known size"); + ObligationCauseCode::SizedConstOrStatic => { + err.note("statics and constants must have a statically known size"); } ObligationCauseCode::InlineAsmSized => { err.note("all inline asm arguments must have a statically known size"); diff --git a/tests/ui/consts/const-slice-array-deref.stderr b/tests/ui/consts/const-slice-array-deref.stderr index 346685380cc6c..b1d069280885d 100644 --- a/tests/ui/consts/const-slice-array-deref.stderr +++ b/tests/ui/consts/const-slice-array-deref.stderr @@ -5,6 +5,7 @@ LL | const ONE: [u16] = [1]; | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u16]` + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/const-slice-array-deref.rs:1:20 diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr index 7931d7adafdb1..8328e19aac22d 100644 --- a/tests/ui/consts/const-unsized.stderr +++ b/tests/ui/consts/const-unsized.stderr @@ -5,6 +5,7 @@ LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:7:18 @@ -13,6 +14,7 @@ LL | const CONST_FOO: str = *"foo"; | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time --> $DIR/const-unsized.rs:11:18 @@ -21,6 +23,7 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:15:20 @@ -29,6 +32,7 @@ LL | static STATIC_BAR: str = *"bar"; | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size error[E0507]: cannot move out of a shared reference --> $DIR/const-unsized.rs:3:35 diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index 8665d9b685223..3980a7e9b93ba 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -30,6 +30,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` + = note: statics and constants must have a statically known size error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr index 64178e6f84390..6f805aec1df02 100644 --- a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr +++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr @@ -5,6 +5,7 @@ LL | static symbol: [usize]; | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[usize]` + = note: statics and constants must have a statically known size error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-36122-accessing-externed-dst.rs:5:20 diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 97e5990750e3c..2cd5a2a49ef5d 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -5,6 +5,7 @@ LL | pub static mut symbol: [i8]; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i8]` + = note: statics and constants must have a statically known size error: aborting due to 1 previous error diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr index 033caf07d8e54..0e6e338c5efeb 100644 --- a/tests/ui/static/issue-24446.stderr +++ b/tests/ui/static/issue-24446.stderr @@ -14,6 +14,7 @@ LL | static foo: dyn Fn() -> u32 = || -> u32 { | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/issue-24446.rs:2:35 diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr index ffbbe218c87a0..3f9b0879c166d 100644 --- a/tests/ui/statics/unsized_type2.stderr +++ b/tests/ui/statics/unsized_type2.stderr @@ -10,6 +10,7 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/unsized_type2.rs:14:45 diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr index 76e015a7238b5..4609e02716fdc 100644 --- a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr @@ -11,6 +11,7 @@ LL | const TEST: Fn = some_fn; | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time --> $DIR/ice-unsized-tuple-const-issue-121443.rs:11:14 From bb7b91224b8aa6dacfb47c13229d635d817bd7fc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Feb 2025 02:21:58 +0000 Subject: [PATCH 10/25] Check signature WF when lowering MIR body --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 18 ++++++++++++++++ tests/crashes/129095.rs | 5 ++++- tests/crashes/132960.rs | 2 +- tests/crashes/134654.rs | 3 +++ tests/crashes/135128.rs | 2 ++ tests/crashes/135570.rs | 3 +++ .../consts/dont-ctfe-unsized-initializer.rs | 7 +++++++ .../dont-ctfe-unsized-initializer.stderr | 21 +++++++++++++++++++ 9 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 tests/ui/consts/dont-ctfe-unsized-initializer.rs create mode 100644 tests/ui/consts/dont-ctfe-unsized-initializer.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a11f025d81ec7..a0837cb0b4788 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -203,7 +203,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua hir::Node::ImplItem(item) => check_impl_item(tcx, item), hir::Node::ForeignItem(item) => check_foreign_item(tcx, item), hir::Node::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)), - _ => unreachable!(), + _ => unreachable!("{node:?}"), }; if let Some(generics) = node.generics() { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 04c9375b83176..5df12ac4d8bc2 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -513,6 +513,24 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & body.tainted_by_errors = Some(error_reported); } + // Also taint the body if it's within a top-level item that is not well formed. + // + // We do this check here and not during `mir_promoted` because that may result + // in borrowck cycles if WF requires looking into an opaque hidden type. + let root = tcx.typeck_root_def_id(def.to_def_id()); + match tcx.def_kind(root) { + DefKind::Fn + | DefKind::AssocFn + | DefKind::Static { .. } + | DefKind::Const + | DefKind::AssocConst => { + if let Err(guar) = tcx.check_well_formed(root.expect_local()) { + body.tainted_by_errors = Some(guar); + } + } + _ => {} + } + run_analysis_to_runtime_passes(tcx, &mut body); tcx.alloc_steal_mir(body) diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs index d82474e18e706..b1bb74708c2d7 100644 --- a/tests/crashes/129095.rs +++ b/tests/crashes/129095.rs @@ -1,10 +1,13 @@ //@ known-bug: rust-lang/rust#129095 //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + pub fn function_with_bytes() -> &'static [u8] { BYTES } pub fn main() { - assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); } diff --git a/tests/crashes/132960.rs b/tests/crashes/132960.rs index 87d0ee7dedebd..c23a339342914 100644 --- a/tests/crashes/132960.rs +++ b/tests/crashes/132960.rs @@ -1,6 +1,6 @@ //@ known-bug: #132960 -#![feature(adt_const_params, const_ptr_read, generic_const_exprs)] +#![feature(adt_const_params, const_ptr_read, generic_const_exprs, unsized_const_params)] const fn concat_strs() -> &'static str where diff --git a/tests/crashes/134654.rs b/tests/crashes/134654.rs index 8a8d18359e96f..f2323fe4ecdcd 100644 --- a/tests/crashes/134654.rs +++ b/tests/crashes/134654.rs @@ -2,6 +2,9 @@ //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir //@ only-x86_64 +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + fn function_with_bytes() -> &'static [u8] { BYTES diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs index 2ce17df824a0c..a8fd1ae1ff56a 100644 --- a/tests/crashes/135128.rs +++ b/tests/crashes/135128.rs @@ -1,6 +1,8 @@ //@ known-bug: #135128 //@ compile-flags: -Copt-level=1 --edition=2021 +#![feature(trivial_bounds)] + async fn return_str() -> str where str: Sized, diff --git a/tests/crashes/135570.rs b/tests/crashes/135570.rs index a9eda97ef9de7..7919ceb26d50d 100644 --- a/tests/crashes/135570.rs +++ b/tests/crashes/135570.rs @@ -2,6 +2,9 @@ //@compile-flags: -Zvalidate-mir -Zmir-enable-passes=+Inline -Copt-level=0 -Zmir-enable-passes=+GVN //@ only-x86_64 +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + fn function_with_bytes( ) -> &'static [u8] { BYTES diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.rs b/tests/ui/consts/dont-ctfe-unsized-initializer.rs new file mode 100644 index 0000000000000..cca38b760dcc8 --- /dev/null +++ b/tests/ui/consts/dont-ctfe-unsized-initializer.rs @@ -0,0 +1,7 @@ +static S: str = todo!(); +//~^ ERROR the size for values of type `str` cannot be known at compilation time + +const C: str = todo!(); +//~^ ERROR the size for values of type `str` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.stderr b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr new file mode 100644 index 0000000000000..e69790fc1823c --- /dev/null +++ b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dont-ctfe-unsized-initializer.rs:1:11 + | +LL | static S: str = todo!(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dont-ctfe-unsized-initializer.rs:4:10 + | +LL | const C: str = todo!(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From cae9ebbe1e09c2878d56ab1425d3765f450fd5fe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 19 Feb 2025 14:08:52 +1100 Subject: [PATCH 11/25] Simplify `Postorder` customization. `Postorder` has a `C: Customization<'tcx>` parameter, that gives it flexibility about how it computes successors. But in practice, there are only two `impls` of `Customization`, and one is for the unit type. This commit simplifies things by removing the generic parameter and replacing it with an `Option`. --- compiler/rustc_middle/src/mir/basic_blocks.rs | 2 +- compiler/rustc_middle/src/mir/traversal.rs | 47 +++++-------------- src/tools/clippy/clippy_utils/src/mir/mod.rs | 2 +- 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 107c3198525a1..171542d1279c7 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -79,7 +79,7 @@ impl<'tcx> BasicBlocks<'tcx> { #[inline] pub fn reverse_postorder(&self) -> &[BasicBlock] { self.cache.reverse_postorder.get_or_init(|| { - let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect(); + let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, None).collect(); rpo.reverse(); rpo }) diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 0e7dcc24dafa6..5950ac295af19 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -104,23 +104,21 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { /// ``` /// /// A Postorder traversal of this graph is `D B C A` or `D C B A` -pub struct Postorder<'a, 'tcx, C> { +pub struct Postorder<'a, 'tcx> { basic_blocks: &'a IndexSlice>, visited: DenseBitSet, visit_stack: Vec<(BasicBlock, Successors<'a>)>, root_is_start_block: bool, - extra: C, + /// A non-empty `extra` allows for a precise calculation of the successors. + extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>, } -impl<'a, 'tcx, C> Postorder<'a, 'tcx, C> -where - C: Customization<'tcx>, -{ +impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new( basic_blocks: &'a IndexSlice>, root: BasicBlock, - extra: C, - ) -> Postorder<'a, 'tcx, C> { + extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>, + ) -> Postorder<'a, 'tcx> { let mut po = Postorder { basic_blocks, visited: DenseBitSet::new_empty(basic_blocks.len()), @@ -140,7 +138,11 @@ where return; } let data = &self.basic_blocks[bb]; - let successors = C::successors(data, self.extra); + let successors = if let Some(extra) = self.extra { + data.mono_successors(extra.0, extra.1) + } else { + data.terminator().successors() + }; self.visit_stack.push((bb, successors)); } @@ -198,10 +200,7 @@ where } } -impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C> -where - C: Customization<'tcx>, -{ +impl<'tcx> Iterator for Postorder<'_, 'tcx> { type Item = BasicBlock; fn next(&mut self) -> Option { @@ -241,32 +240,12 @@ pub fn postorder<'a, 'tcx>( reverse_postorder(body).rev() } -/// Lets us plug in some additional logic and data into a Postorder traversal. Or not. -pub trait Customization<'tcx>: Copy { - fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>; -} - -impl<'tcx> Customization<'tcx> for () { - fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> { - data.terminator().successors() - } -} - -impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) { - fn successors<'a>( - data: &'a BasicBlockData<'tcx>, - (tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>), - ) -> Successors<'a> { - data.mono_successors(tcx, instance) - } -} - pub fn mono_reachable_reverse_postorder<'a, 'tcx>( body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, ) -> Vec { - let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance)); + let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, Some((tcx, instance))); let mut items = Vec::with_capacity(body.basic_blocks.len()); while let Some(block) = iter.next() { items.push(block); diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 637c0bafd964a..ffcfcd240ea5a 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - locals.len() ]; - traversal::Postorder::new(&mir.basic_blocks, location.block, ()) + traversal::Postorder::new(&mir.basic_blocks, location.block, None) .collect::>() .into_iter() .rev() From 81ab20f34e5447108c8103c10cd3f106f338e7e1 Mon Sep 17 00:00:00 2001 From: Jordan McQueen Date: Thu, 20 Feb 2025 10:37:28 +0000 Subject: [PATCH 12/25] Update references to cc_detect.rs The locations of these files have since been changed. This is a simple change to update the references to these files. --- config.example.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.example.toml b/config.example.toml index fd27b24e46191..a17d3ec9f8841 100644 --- a/config.example.toml +++ b/config.example.toml @@ -793,12 +793,12 @@ # C compiler to be used to compile C code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. -# See `src/bootstrap/cc_detect.rs` for details. +# See `src/bootstrap/src/utils/cc_detect.rs` for details. #cc = "cc" (path) # C++ compiler to be used to compile C++ code (e.g. LLVM and our LLVM shims). # This is only used for host targets. -# See `src/bootstrap/cc_detect.rs` for details. +# See `src/bootstrap/src/utils/cc_detect.rs` for details. #cxx = "c++" (path) # Archiver to be used to assemble static libraries compiled from C/C++ code. From ea7180813b4dface2bc02a9095ce1ebb8c64d4de Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 14 Feb 2025 17:27:49 +0000 Subject: [PATCH 13/25] Create safe helper for LLVMSetDLLStorageClass --- compiler/rustc_codegen_llvm/src/callee.rs | 6 ++---- compiler/rustc_codegen_llvm/src/consts.rs | 8 ++------ compiler/rustc_codegen_llvm/src/llvm/mod.rs | 6 ++++++ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index aa9a0f34f55e9..90075e1c10552 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -66,9 +66,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t // LLVM will prefix the name with `__imp_`. Ideally, we'd like the // existing logic below to set the Storage Class, but it has an // exemption for MinGW for backwards compatibility. - unsafe { - llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); - } + llvm::set_dllimport_storage_class(llfn); llfn } else { cx.declare_fn(sym, fn_abi, Some(instance)) @@ -150,7 +148,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t && library.kind.is_dllimport() && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc") { - llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); + llvm::set_dllimport_storage_class(llfn); } if cx.should_assume_dso_local(llfn, true) { diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 4a5491ec7a18c..5ab437d27c208 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -375,9 +375,7 @@ impl<'ll> CodegenCx<'ll, '_> { // is actually present in the current crate. We can find out via the // is_codegened_item query. if !self.tcx.is_codegened_item(def_id) { - unsafe { - llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); - } + llvm::set_dllimport_storage_class(g); } } } @@ -387,9 +385,7 @@ impl<'ll> CodegenCx<'ll, '_> { && library.kind.is_dllimport() { // For foreign (native) libs we know the exact storage type to use. - unsafe { - llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); - } + llvm::set_dllimport_storage_class(g); } self.instances.borrow_mut().insert(instance, g); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index efc9cf2ef691b..7f57e64063794 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -403,3 +403,9 @@ pub(crate) fn add_module_flag_str( ); } } + +pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) { + unsafe { + LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport); + } +} From ce7f58bd91548fd8674aaceb670f827de26d4216 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 14 Feb 2025 17:27:49 +0000 Subject: [PATCH 14/25] Merge two operations that were always performed together --- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/callee.rs | 102 +++++++++---------- compiler/rustc_codegen_llvm/src/consts.rs | 11 +- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 6 ++ compiler/rustc_codegen_llvm/src/mono_item.rs | 25 +++-- 5 files changed, 70 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 7262fce491191..3e25b94961b00 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -362,8 +362,8 @@ fn fat_lto( ptr as *const *const libc::c_char, symbols_below_threshold.len() as libc::size_t, ); - save_temp_bitcode(cgcx, &module, "lto.after-restriction"); } + save_temp_bitcode(cgcx, &module, "lto.after-restriction"); } Ok(LtoModuleCodegen::Fat(module)) diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 90075e1c10552..ea9ab5c02bd6c 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -97,65 +97,61 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t // has been applied to the definition (wherever that definition may be). llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage); - unsafe { - let is_generic = instance.args.non_erasable_generics().next().is_some(); - - let is_hidden = if is_generic { - // This is a monomorphization of a generic function. - if !(cx.tcx.sess.opts.share_generics() - || tcx.codegen_fn_attrs(instance_def_id).inline - == rustc_attr_parsing::InlineAttr::Never) - { - // When not sharing generics, all instances are in the same - // crate and have hidden visibility. - true - } else { - if let Some(instance_def_id) = instance_def_id.as_local() { - // This is a monomorphization of a generic function - // defined in the current crate. It is hidden if: - // - the definition is unreachable for downstream - // crates, or - // - the current crate does not re-export generics - // (because the crate is a C library or executable) - cx.tcx.is_unreachable_local_definition(instance_def_id) - || !cx.tcx.local_crate_exports_generics() - } else { - // This is a monomorphization of a generic function - // defined in an upstream crate. It is hidden if: - // - it is instantiated in this crate, and - // - the current crate does not re-export generics - instance.upstream_monomorphization(tcx).is_none() - && !cx.tcx.local_crate_exports_generics() - } - } - } else { - // This is a non-generic function. It is hidden if: - // - it is instantiated in the local crate, and - // - it is defined an upstream crate (non-local), or - // - it is not reachable - cx.tcx.is_codegened_item(instance_def_id) - && (!instance_def_id.is_local() - || !cx.tcx.is_reachable_non_generic(instance_def_id)) - }; - if is_hidden { - llvm::set_visibility(llfn, llvm::Visibility::Hidden); - } + let is_generic = instance.args.non_erasable_generics().next().is_some(); - // MinGW: For backward compatibility we rely on the linker to decide whether it - // should use dllimport for functions. - if cx.use_dll_storage_attrs - && let Some(library) = tcx.native_library(instance_def_id) - && library.kind.is_dllimport() - && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc") + let is_hidden = if is_generic { + // This is a monomorphization of a generic function. + if !(cx.tcx.sess.opts.share_generics() + || tcx.codegen_fn_attrs(instance_def_id).inline + == rustc_attr_parsing::InlineAttr::Never) { - llvm::set_dllimport_storage_class(llfn); + // When not sharing generics, all instances are in the same + // crate and have hidden visibility. + true + } else { + if let Some(instance_def_id) = instance_def_id.as_local() { + // This is a monomorphization of a generic function + // defined in the current crate. It is hidden if: + // - the definition is unreachable for downstream + // crates, or + // - the current crate does not re-export generics + // (because the crate is a C library or executable) + cx.tcx.is_unreachable_local_definition(instance_def_id) + || !cx.tcx.local_crate_exports_generics() + } else { + // This is a monomorphization of a generic function + // defined in an upstream crate. It is hidden if: + // - it is instantiated in this crate, and + // - the current crate does not re-export generics + instance.upstream_monomorphization(tcx).is_none() + && !cx.tcx.local_crate_exports_generics() + } } + } else { + // This is a non-generic function. It is hidden if: + // - it is instantiated in the local crate, and + // - it is defined an upstream crate (non-local), or + // - it is not reachable + cx.tcx.is_codegened_item(instance_def_id) + && (!instance_def_id.is_local() + || !cx.tcx.is_reachable_non_generic(instance_def_id)) + }; + if is_hidden { + llvm::set_visibility(llfn, llvm::Visibility::Hidden); + } - if cx.should_assume_dso_local(llfn, true) { - llvm::LLVMRustSetDSOLocal(llfn, true); - } + // MinGW: For backward compatibility we rely on the linker to decide whether it + // should use dllimport for functions. + if cx.use_dll_storage_attrs + && let Some(library) = tcx.native_library(instance_def_id) + && library.kind.is_dllimport() + && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc") + { + llvm::set_dllimport_storage_class(llfn); } + cx.assume_dso_local(llfn, true); + llfn }; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 5ab437d27c208..330e8a8f4069d 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -336,12 +336,7 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::set_thread_local_mode(g, self.tls_model); } - let dso_local = self.should_assume_dso_local(g, true); - if dso_local { - unsafe { - llvm::LLVMRustSetDSOLocal(g, true); - } - } + let dso_local = self.assume_dso_local(g, true); if !def_id.is_local() { let needs_dll_storage_attr = self.use_dll_storage_attrs @@ -456,9 +451,7 @@ impl<'ll> CodegenCx<'ll, '_> { set_global_alignment(self, g, alloc.align); llvm::set_initializer(g, v); - if self.should_assume_dso_local(g, true) { - llvm::LLVMRustSetDSOLocal(g, true); - } + self.assume_dso_local(g, true); // Forward the allocation's mutability (picked by the const interner) to LLVM. if alloc.mutability.is_not() { diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 7f57e64063794..5ec934241314c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -409,3 +409,9 @@ pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) { LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport); } } + +pub(crate) fn set_dso_local<'ll>(v: &'ll Value) { + unsafe { + LLVMRustSetDSOLocal(v, true); + } +} diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 70edee21bd63a..a64627eaf5986 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -38,11 +38,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::set_linkage(g, base::linkage_to_llvm(linkage)); llvm::set_visibility(g, base::visibility_to_llvm(visibility)); - unsafe { - if self.should_assume_dso_local(g, false) { - llvm::LLVMRustSetDSOLocal(g, true); - } - } + self.assume_dso_local(g, false); self.instances.borrow_mut().insert(instance, g); } @@ -79,9 +75,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { debug!("predefine_fn: instance = {:?}", instance); - if self.should_assume_dso_local(lldecl, false) { - unsafe { llvm::LLVMRustSetDSOLocal(lldecl, true) }; - } + self.assume_dso_local(lldecl, false); self.instances.borrow_mut().insert(instance, lldecl); } @@ -90,11 +84,16 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { impl CodegenCx<'_, '_> { /// Whether a definition or declaration can be assumed to be local to a group of /// libraries that form a single DSO or executable. - pub(crate) fn should_assume_dso_local( - &self, - llval: &llvm::Value, - is_declaration: bool, - ) -> bool { + /// Marks the local as DSO if so. + pub(crate) fn assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool { + let assume = self.should_assume_dso_local(llval, is_declaration); + if assume { + llvm::set_dso_local(llval); + } + assume + } + + fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool { let linkage = llvm::get_linkage(llval); let visibility = llvm::get_visibility(llval); From c23bf48e4fedafee67ae1e52edeb8f3f94268a7d Mon Sep 17 00:00:00 2001 From: usamoi Date: Mon, 3 Feb 2025 16:43:24 +0800 Subject: [PATCH 15/25] infer linker flavor by linker name if it's sufficiently specific --- compiler/rustc_target/src/spec/mod.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f7e467b0c1155..60e1699b11d68 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -303,15 +303,16 @@ impl LinkerFlavor { } } - fn infer_linker_hints(linker_stem: &str) -> (Option, Option) { + fn infer_linker_hints(linker_stem: &str) -> Result, Option)> { // Remove any version postfix. let stem = linker_stem .rsplit_once('-') .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs)) .unwrap_or(linker_stem); - // GCC/Clang can have an optional target prefix. - if stem == "emcc" + if stem == "llvm-bitcode-linker" { + Ok(Self::Llbc) + } else if stem == "emcc" // GCC/Clang can have an optional target prefix. || stem == "gcc" || stem.ends_with("-gcc") || stem == "g++" @@ -321,7 +322,7 @@ impl LinkerFlavor { || stem == "clang++" || stem.ends_with("-clang++") { - (Some(Cc::Yes), Some(Lld::No)) + Err((Some(Cc::Yes), Some(Lld::No))) } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") || stem == "ld.lld" @@ -329,11 +330,11 @@ impl LinkerFlavor { || stem == "rust-lld" || stem == "lld-link" { - (Some(Cc::No), Some(Lld::Yes)) + Err((Some(Cc::No), Some(Lld::Yes))) } else if stem == "ld" || stem.ends_with("-ld") || stem == "link" { - (Some(Cc::No), Some(Lld::No)) + Err((Some(Cc::No), Some(Lld::No))) } else { - (None, None) + Err((None, None)) } } @@ -357,7 +358,10 @@ impl LinkerFlavor { } pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor { - self.with_hints(LinkerFlavor::infer_linker_hints(linker_stem)) + match LinkerFlavor::infer_linker_hints(linker_stem) { + Ok(linker_flavor) => linker_flavor, + Err(hints) => self.with_hints(hints), + } } pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option { From d5128f92745774a93cd4384a71c7df727bc87377 Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Thu, 20 Feb 2025 15:05:06 +0100 Subject: [PATCH 16/25] avr-rjmp-offset: Explain `.target_cpu()` --- tests/run-make/avr-rjmp-offset/rmake.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/run-make/avr-rjmp-offset/rmake.rs b/tests/run-make/avr-rjmp-offset/rmake.rs index 73b6ab3977e97..da314f26ca782 100644 --- a/tests/run-make/avr-rjmp-offset/rmake.rs +++ b/tests/run-make/avr-rjmp-offset/rmake.rs @@ -23,6 +23,10 @@ fn main() { .opt_level("s") .panic("abort") .target("avr-none") + // rust-lld has some troubles understanding the -mmcu flag, so for the + // time being let's tell rustc to emit binary that's compatible with the + // target CPU that lld defaults to, i.e. just `avr` (that's simply the + // minimal common instruction set across all AVRs) .target_cpu("avr") // normally one links with `avr-gcc`, but this is not available in CI, // hence this test diverges from the default behavior to enable linking From 18c210c7869b5786acde4d343a47df99113dba9b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:06:53 +0000 Subject: [PATCH 17/25] Workaround Cranelift not yet properly supporting vectors smaller than 128bit While it would technically be possible to workaround this in cg_clif, it quickly becomes very messy and would likely cause correctness issues. Working around it in rustc instead is much simper and won't have any negative impact for code running on stable as vectors smaller than 128bit can only be made on nightly using core::simd or #[repr(simd)]. --- compiler/rustc_target/src/callconv/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index c2a176facdfa1..b90a006ac51ad 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -737,7 +737,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { // to 128-bit-sized vectors. "x86" if spec.rustc_abi == Some(RustcAbi::X86Sse2) => arg.layout.size.bits() <= 128, "x86_64" if spec.rustc_abi != Some(RustcAbi::X86Softfloat) => { - arg.layout.size.bits() <= 128 + // FIXME once https://github.com/bytecodealliance/wasmtime/issues/10254 is fixed + // accept vectors up to 128bit rather than vectors of exactly 128bit. + arg.layout.size.bits() == 128 } // So far, we haven't implemented this logic for any other target. _ => false, From c2aed39ea7285d86d4a9c1b02e221bddc1d9a45f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 20 Feb 2025 08:15:07 -0800 Subject: [PATCH 18/25] Update docs for default features of wasm targets LLVM 20 enabled the `nontrapping-fptoint` and `bulk-memory` features by default, so this updates the corresponding documentation for the `wasm32-*` targets (which all point to `wasm32-unknown-unknown`). cc #137315 --- src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 73264aba85809..ba95ab7af6d1a 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -129,6 +129,8 @@ As of the time of this writing the proposals that are enabled by default (the * `mutable-globals` * `reference-types` * `sign-ext` +* `nontrapping-fptoint` (Rust 1.87.0+, LLVM 20+) +* `bulk-memory` (Rust 1.87.0+, LLVM 20+) If you're compiling WebAssembly code for an engine that does not support a feature in LLVM's default feature set then the feature must be disabled at From 32a1ff1aafba04670f557c7175d6962148a0260f Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Thu, 20 Feb 2025 16:40:50 +0000 Subject: [PATCH 19/25] Make x86 QNX target name consistent with other Rust targets --- compiler/rustc_target/src/spec/mod.rs | 2 +- .../{i586_pc_nto_qnx700.rs => i686_pc_nto_qnx700.rs} | 0 src/doc/rustc/src/platform-support.md | 2 +- src/doc/rustc/src/platform-support/nto-qnx.md | 2 +- src/tools/tidy/src/target_policy.rs | 1 + tests/assembly/targets/targets-elf.rs | 6 +++--- 6 files changed, 7 insertions(+), 6 deletions(-) rename compiler/rustc_target/src/spec/targets/{i586_pc_nto_qnx700.rs => i686_pc_nto_qnx700.rs} (100%) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f7e467b0c1155..e9733113acc78 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2001,7 +2001,7 @@ supported_targets! { ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock), ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800), - ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), + ("i686-pc-nto-qnx700", i686_pc_nto_qnx700), ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos), ("armv7-unknown-linux-ohos", armv7_unknown_linux_ohos), diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs similarity index 100% rename from compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index b5cd3864620d3..86a210a0d9c0d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -309,10 +309,10 @@ target | std | host | notes [`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux with musl 1.2.3 [`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX) [`i386-apple-ios`](platform-support/apple-ios.md) | ✓ | | 32-bit x86 iOS (Penryn) [^x86_32-floats-return-ABI] -[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI] [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86 (original Pentium) [^x86_32-floats-x87] [`i586-unknown-redox`](platform-support/redox.md) | ✓ | | 32-bit x86 Redox OS (PentiumPro) [^x86_32-floats-x87] [`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI] +[`i686-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI] diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 339741f14727d..77e8caaee4cdc 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -31,7 +31,7 @@ Currently, the following QNX versions and compilation targets are supported: | `aarch64-unknown-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | AArch64 | ? | ✓ | | `x86_64-pc-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | x86_64 | ? | ✓ | | `aarch64-unknown-nto-qnx700` | QNX Neutrino 7.0 | AArch64 | ? | ✓ | -| `i586-pc-nto-qnx700` | QNX Neutrino 7.0 | x86 | | ✓ | +| `i686-pc-nto-qnx700` | QNX Neutrino 7.0 | x86 | | ✓ | On QNX Neutrino 7.0 and 7.1, `io-pkt` is used as network stack by default. QNX Neutrino 7.1 includes the optional network stack `io-sock`. diff --git a/src/tools/tidy/src/target_policy.rs b/src/tools/tidy/src/target_policy.rs index 776221d306233..b2681934417cb 100644 --- a/src/tools/tidy/src/target_policy.rs +++ b/src/tools/tidy/src/target_policy.rs @@ -21,6 +21,7 @@ const EXCEPTIONS: &[&str] = &[ "xtensa_esp32s2_espidf", "xtensa_esp32s3_none_elf", "xtensa_esp32s3_espidf", + "i586_pc_nto_qnx700", // Renamed to i686-pc-nto-qnx700, see https://github.com/rust-lang/rust/issues/136495 ]; pub fn check(root_path: &Path, bad: &mut bool) { diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index b5c0ee5a10741..3e73d2c6eb72d 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -216,9 +216,9 @@ //@ revisions: hexagon_unknown_none_elf //@ [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf //@ [hexagon_unknown_none_elf] needs-llvm-components: hexagon -//@ revisions: i586_pc_nto_qnx700 -//@ [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700 -//@ [i586_pc_nto_qnx700] needs-llvm-components: x86 +//@ revisions: i686_pc_nto_qnx700 +//@ [i686_pc_nto_qnx700] compile-flags: --target i686-pc-nto-qnx700 +//@ [i686_pc_nto_qnx700] needs-llvm-components: x86 //@ revisions: i586_unknown_linux_gnu //@ [i586_unknown_linux_gnu] compile-flags: --target i586-unknown-linux-gnu //@ [i586_unknown_linux_gnu] needs-llvm-components: x86 From 7ba3d7b54e7688f6f1a0fd22fe274ee7b06fea3e Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: [PATCH 20/25] Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- compiler/rustc_abi/src/callconv.rs | 2 -- compiler/rustc_abi/src/layout.rs | 23 ++++++------ compiler/rustc_abi/src/lib.rs | 35 +++++++++---------- .../src/value_and_place.rs | 4 +-- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 2 +- compiler/rustc_codegen_gcc/src/type_of.rs | 13 +++---- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 13 +++---- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 +-- .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../src/interpret/validity.rs | 8 ++--- .../src/util/check_validity_requirement.rs | 16 +++++---- compiler/rustc_middle/src/ty/layout.rs | 3 +- compiler/rustc_mir_transform/src/gvn.rs | 5 ++- .../rustc_smir/src/rustc_smir/convert/abi.rs | 1 - .../rustc_target/src/callconv/loongarch.rs | 2 +- compiler/rustc_target/src/callconv/mod.rs | 3 +- compiler/rustc_target/src/callconv/riscv.rs | 2 +- compiler/rustc_target/src/callconv/x86.rs | 4 +-- compiler/rustc_target/src/callconv/x86_64.rs | 2 -- .../rustc_target/src/callconv/x86_win64.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 4 +-- compiler/rustc_ty_utils/src/layout.rs | 21 +++++------ .../rustc_ty_utils/src/layout/invariant.rs | 15 ++++---- compiler/stable_mir/src/abi.rs | 6 +--- .../rust-analyzer/crates/hir-ty/src/layout.rs | 12 +++---- 26 files changed, 93 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index 9fb70b80c9efb..4529ab8058e9a 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty: TyAbiInterface<'a, C> + Copy, { match self.backend_repr { - BackendRepr::Uninhabited => Err(Heterogeneous), - // The primitive for this algorithm. BackendRepr::Scalar(scalar) => { let kind = match scalar.primitive() { diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 45cd0b517f6c7..53243266f992b 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -130,6 +130,7 @@ impl LayoutCalculator { }, backend_repr: BackendRepr::ScalarPair(a, b), largest_niche, + uninhabited: false, align, size, max_repr_align: None, @@ -221,8 +222,9 @@ impl LayoutCalculator { LayoutData { variants: Variants::Empty, fields: FieldsShape::Primitive, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -400,6 +402,7 @@ impl LayoutCalculator { fields: FieldsShape::Union(union_field_count), backend_repr: abi, largest_niche: None, + uninhabited: false, align, size: size.align_to(align.abi), max_repr_align, @@ -447,7 +450,6 @@ impl LayoutCalculator { Scalar::Union { .. } => {} }; match &mut st.backend_repr { - BackendRepr::Uninhabited => {} BackendRepr::Scalar(scalar) => hide_niches(scalar), BackendRepr::ScalarPair(a, b) => { hide_niches(a); @@ -639,9 +641,8 @@ impl LayoutCalculator { let same_size = size == variant_layouts[largest_variant_index].size; let same_align = align == variant_layouts[largest_variant_index].align; - let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) { - BackendRepr::Uninhabited - } else if same_size && same_align && others_zst { + let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited()); + let abi = if same_size && same_align && others_zst { match variant_layouts[largest_variant_index].backend_repr { // When the total alignment and size match, we can use the // same ABI as the scalar variant with the reserved niche. @@ -683,6 +684,7 @@ impl LayoutCalculator { }, backend_repr: abi, largest_niche, + uninhabited, size, align, max_repr_align, @@ -853,9 +855,8 @@ impl LayoutCalculator { }; let mut abi = BackendRepr::Memory { sized: true }; - if layout_variants.iter().all(|v| v.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } else if tag.size(dl) == size { + let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited()); + if tag.size(dl) == size { // Make sure we only use scalar layout when the enum is entirely its // own tag (i.e. it has no padding nor any non-ZST variant fields). abi = BackendRepr::Scalar(tag); @@ -995,6 +996,7 @@ impl LayoutCalculator { memory_index: [0].into(), }, largest_niche, + uninhabited, backend_repr: abi, align, size, @@ -1355,9 +1357,7 @@ impl LayoutCalculator { _ => {} } } - if fields.iter().any(|f| f.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } + let uninhabited = fields.iter().any(|f| f.is_uninhabited()); let unadjusted_abi_align = if repr.transparent() { match layout_of_single_non_zst_field { @@ -1378,6 +1378,7 @@ impl LayoutCalculator { fields: FieldsShape::Arbitrary { offsets, memory_index }, backend_repr: abi, largest_niche, + uninhabited, align, size, max_repr_align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index dbb4bed5cdd99..14a8a57920049 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1404,7 +1404,6 @@ impl AddressSpace { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum BackendRepr { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -1423,10 +1422,9 @@ impl BackendRepr { #[inline] pub fn is_unsized(&self) -> bool { match *self { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) - | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { + false + } BackendRepr::Memory { sized } => !sized, } } @@ -1445,12 +1443,6 @@ impl BackendRepr { } } - /// Returns `true` if this is an uninhabited type - #[inline] - pub fn is_uninhabited(&self) -> bool { - matches!(*self, BackendRepr::Uninhabited) - } - /// Returns `true` if this is a scalar type #[inline] pub fn is_scalar(&self) -> bool { @@ -1471,7 +1463,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { cx.data_layout().vector_align(element.size(cx) * count) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1492,7 +1484,7 @@ impl BackendRepr { // to make the size a multiple of align (e.g. for vectors of size 3). (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1506,9 +1498,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { BackendRepr::Vector { element: element.to_union(), count } } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - BackendRepr::Memory { sized: true } - } + BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true }, } } @@ -1704,6 +1694,11 @@ pub struct LayoutData { /// The leaf scalar with the largest number of invalid values /// (i.e. outside of its `valid_range`), if it exists. pub largest_niche: Option, + /// Is this type known to be uninhabted? + /// + /// This is separate from BackendRepr, because an uninhabited return type may require special + /// consideration based on its size or other attributes. + pub uninhabited: bool, pub align: AbiAndPrefAlign, pub size: Size, @@ -1735,14 +1730,14 @@ impl LayoutData { /// Returns `true` if this is an aggregate type (including a ScalarPair!) pub fn is_aggregate(&self) -> bool { match self.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true, } } /// Returns `true` if this is an uninhabited type pub fn is_uninhabited(&self) -> bool { - self.backend_repr.is_uninhabited() + self.uninhabited } pub fn scalar(cx: &C, scalar: Scalar) -> Self { @@ -1778,6 +1773,7 @@ impl LayoutData { fields: FieldsShape::Primitive, backend_repr: BackendRepr::Scalar(scalar), largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1802,6 +1798,7 @@ where backend_repr, fields, largest_niche, + uninhabited, variants, max_repr_align, unadjusted_abi_align, @@ -1813,6 +1810,7 @@ where .field("abi", backend_repr) .field("fields", fields) .field("largest_niche", largest_niche) + .field("uninhabited", uninhabited) .field("variants", variants) .field("max_repr_align", max_repr_align) .field("unadjusted_abi_align", unadjusted_abi_align) @@ -1877,7 +1875,6 @@ impl LayoutData { BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { false } - BackendRepr::Uninhabited => self.size.bytes() == 0, BackendRepr::Memory { sized } => sized && self.size.bytes() == 0, } } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index a9b8e1bd39353..1b3f86c8405de 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> { } CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), CPlaceInner::Addr(to_ptr, None) => { - if dst_layout.size == Size::ZERO - || dst_layout.backend_repr == BackendRepr::Uninhabited - { + if dst_layout.size == Size::ZERO { return; } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 5322b731d8bb5..433868e238a4c 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -315,7 +315,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 8b8b54753e7fd..bac4fc51300a2 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( false, ); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => {} } let name = match *layout.ty.kind() { @@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 7e1a9d361e6fb..f68365f6c69bc 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -476,7 +476,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let layout = self.layout_of(tp_ty).layout; let use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index b0b6da869da68..ba01fbff38539 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>( let element = layout.scalar_llvm_type_at(cx, element); return cx.type_vector(element, count); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} + BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} } let name = match layout.ty.kind() { @@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { fn is_llvm_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_llvm_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 958a52a2cb1dc..faf1300e4731e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -422,9 +422,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { See ", ); } - BackendRepr::Uninhabited - | BackendRepr::ScalarPair(_, _) - | BackendRepr::Memory { sized: false } => bug!(), + BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(), }) }; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 5d905cff1f216..36da9037e43d9 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -385,7 +385,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { (Immediate::Uninit, _) => Immediate::Uninit, // If the field is uninhabited, we can forget the data (can happen in ConstProp). // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that - // has an `Uninhabited` variant, which means this case is possible. + // has an uninhabited variant, which means this case is possible. _ if layout.is_uninhabited() => Immediate::Uninit, // the field contains no information, can be left uninit // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0ac34f4633b57..3667cc84d708e 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1274,11 +1274,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). + if val.layout.is_uninhabited() { + let ty = val.layout.ty; + throw_validation_failure!(self.path, UninhabitedVal { ty }); + } match val.layout.backend_repr { - BackendRepr::Uninhabited => { - let ty = val.layout.ty; - throw_validation_failure!(self.path, UninhabitedVal { ty }); - } BackendRepr::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 79baf91c3ce64..6426bca2332d4 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -111,13 +111,15 @@ fn check_validity_requirement_lax<'tcx>( }; // Check the ABI. - let valid = match this.backend_repr { - BackendRepr::Uninhabited => false, // definitely UB - BackendRepr::Scalar(s) => scalar_allows_raw_init(s), - BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), - BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), - BackendRepr::Memory { .. } => true, // Fields are checked below. - }; + let valid = !this.is_uninhabited() // definitely UB if uninhabited + && match this.backend_repr { + BackendRepr::Scalar(s) => scalar_allows_raw_init(s), + BackendRepr::ScalarPair(s1, s2) => { + scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2) + } + BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), + BackendRepr::Memory { .. } => true, // Fields are checked below. + }; if !valid { // This is definitely not okay. return Ok(false); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 19fa832357499..eb14ed20fbace 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -794,8 +794,9 @@ where Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, }, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: tcx.data_layout.i8_align, size: Size::ZERO, max_repr_align: None, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 77a3854ebdef3..2f8a305019999 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1558,8 +1558,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return true; }; + if layout.uninhabited { + return true; + } + match layout.backend_repr { - BackendRepr::Uninhabited => true, BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index fb2e838cdc998..a627e0e69b62f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -202,7 +202,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { match *self { - rustc_abi::BackendRepr::Uninhabited => ValueAbi::Uninhabited, rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)), rustc_abi::BackendRepr::ScalarPair(first, second) => { ValueAbi::ScalarPair(first.stable(tables), second.stable(tables)) diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 47566bde6b4a4..3fa67c624a7be 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -80,7 +80,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index c2a176facdfa1..e5f986269ddc0 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -38,7 +38,7 @@ mod xtensa; pub enum PassMode { /// Ignore the argument. /// - /// The argument is either uninhabited or a ZST. + /// The argument is a ZST. Ignore, /// Pass the argument directly. /// @@ -350,7 +350,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, Scalar, Size) -> ArgAttributes, ) -> Self { let mode = match layout.backend_repr { - BackendRepr::Uninhabited => PassMode::Ignore, BackendRepr::Scalar(scalar) => { PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)) } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 265ae20f9919d..785175229b031 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -86,7 +86,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 5f4f4cd57f654..7e5aab0201b6d 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -108,9 +108,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, { match layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) => false, BackendRepr::Vector { .. } => true, BackendRepr::Memory { .. } => { for i in 0..layout.fields.count() { diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index b15d82c26dac2..ab306e202396b 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -51,8 +51,6 @@ where } let mut c = match layout.backend_repr { - BackendRepr::Uninhabited => return Ok(()), - BackendRepr::Scalar(scalar) => match scalar.primitive() { Primitive::Int(..) | Primitive::Pointer(_) => Class::Int, Primitive::Float(_) => Class::Sse, diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 2ef5127de04ae..4d99a9f9ba064 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -8,7 +8,7 @@ use crate::spec::{HasTargetSpec, RustcAbi}; pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {} + BackendRepr::Memory { sized: false } => {} BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => { match a.layout.size.bits() { 8 => a.cast_to(Reg::i8()), diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c5d2d0afbfad2..2d20ef3d690dd 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -472,9 +472,7 @@ fn fn_abi_sanity_check<'tcx>( // `layout.backend_repr` and ignore everything else. We should just reject //`Aggregate` entirely here, but some targets need to be fixed first. match arg.layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } => {} + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => {} BackendRepr::ScalarPair(..) => { panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 556512e0236e5..b6a14d147cad4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -348,19 +348,17 @@ fn layout_of_uncached<'tcx>( .checked_mul(count, dl) .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?; - let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let abi = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; tcx.mk_layout(LayoutData { variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr: abi, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -375,6 +373,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -390,6 +389,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -555,6 +555,7 @@ fn layout_of_uncached<'tcx>( fields, backend_repr: abi, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1014,13 +1015,8 @@ fn coroutine_layout<'tcx>( size = size.align_to(align.abi); - let abi = if prefix.backend_repr.is_uninhabited() - || variants.iter().all(|v| v.backend_repr.is_uninhabited()) - { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let uninhabited = prefix.uninhabited || variants.iter().all(|v| v.is_uninhabited()); + let abi = BackendRepr::Memory { sized: true }; // this is similar to how ReprOptions populates its field_shuffle_seed let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash(); @@ -1041,6 +1037,7 @@ fn coroutine_layout<'tcx>( // See , . // FIXME: Remove when is implemented and aliased coroutine fields are wrapped in `UnsafePinned`. largest_niche: None, + uninhabited, size, align, max_repr_align: None, diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 8d5403ed32468..5ea6716c5ca14 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -10,7 +10,11 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou // Type-level uninhabitedness should always imply ABI uninhabitedness. if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) { - assert!(layout.is_uninhabited()); + assert!( + layout.is_uninhabited(), + "{:?} is type-level uninhabited but not ABI-uninhabited?", + layout.ty + ); } if layout.size.bytes() % layout.align.abi.bytes() != 0 { @@ -71,7 +75,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou let Some((align, size)) = align.zip(size) else { assert_matches!( layout.layout.backend_repr(), - BackendRepr::Uninhabited | BackendRepr::Memory { .. }, + BackendRepr::Memory { .. }, "ABI unexpectedly missing alignment and/or size in {layout:#?}" ); return; @@ -235,7 +239,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`. // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair. } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check. + BackendRepr::Memory { .. } => {} // Nothing to check. } } @@ -291,8 +295,8 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou || variant.is_uninhabited() { // These are never actually accessed anyway, so we can skip the coherence check - // for them. They also fail that check, since they have - // `Aggregate`/`Uninhabited` ABI even when the main type is + // for them. They also fail that check, since they may have + // a different ABI even when the main type is // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size // 0, and sometimes, variants without fields have non-0 size.) continue; @@ -306,7 +310,6 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => { scalar_coherent(a1, a2) && scalar_coherent(b1, b2) } - (BackendRepr::Uninhabited, _) => true, (BackendRepr::Memory { .. }, _) => true, _ => false, }; diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 861b6692b5367..091f3e1a95e95 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -227,7 +227,6 @@ pub enum TagEncoding { /// in terms of categories of C types there are ABI rules for. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum ValueAbi { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -244,10 +243,7 @@ impl ValueAbi { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { match *self { - ValueAbi::Uninhabited - | ValueAbi::Scalar(_) - | ValueAbi::ScalarPair(..) - | ValueAbi::Vector { .. } => false, + ValueAbi::Scalar(_) | ValueAbi::ScalarPair(..) | ValueAbi::Vector { .. } => false, ValueAbi::Aggregate { sized } => !sized, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index b6f7c44c2aeee..f5a7b6581230f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -194,6 +194,7 @@ fn layout_of_simd_ty( fields, backend_repr: BackendRepr::Vector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -297,20 +298,17 @@ pub fn layout_of_ty_query( .checked_mul(count, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let backend_repr = - if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let backend_repr = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; Layout { variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -325,6 +323,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -337,6 +336,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, From c33fb5ae854e8ac26d75e72b7cb31519730f51d6 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 21:28:54 -0600 Subject: [PATCH 21/25] Update ui tests with `LayoutData { uninhabited: ... }` etc --- tests/ui/abi/c-zst.aarch64-darwin.stderr | 2 + tests/ui/abi/c-zst.powerpc-linux.stderr | 2 + tests/ui/abi/c-zst.s390x-linux.stderr | 2 + tests/ui/abi/c-zst.sparc64-linux.stderr | 2 + tests/ui/abi/c-zst.x86_64-linux.stderr | 2 + .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 2 + tests/ui/abi/debug.stderr | 24 +++++++++ tests/ui/abi/sysv64-zst.stderr | 2 + tests/ui/layout/debug.stderr | 22 +++++++- tests/ui/layout/hexagon-enum.stderr | 10 ++++ ...-scalarpair-payload-might-be-uninit.stderr | 17 +++++++ .../issue-96185-overaligned-enum.stderr | 6 +++ tests/ui/layout/thumb-enum.stderr | 10 ++++ .../layout/zero-sized-array-enum-niche.stderr | 13 +++++ ...-variants.aarch64-unknown-linux-gnu.stderr | 50 +++++++++++++++++-- ...-c-dead-variants.armebv7r-none-eabi.stderr | 50 +++++++++++++++++-- ...-dead-variants.i686-pc-windows-msvc.stderr | 50 +++++++++++++++++-- ...d-variants.x86_64-unknown-linux-gnu.stderr | 50 +++++++++++++++++-- tests/ui/repr/repr-c-int-dead-variants.stderr | 50 +++++++++++++++++-- .../type/pattern_types/range_patterns.stderr | 9 ++++ 20 files changed, 349 insertions(+), 26 deletions(-) diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index c8f7d0a517c4c..57cc48aa9cf47 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 1015f7d889880..6738017673003 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 1015f7d889880..6738017673003 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 1015f7d889880..6738017673003 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index c8f7d0a517c4c..57cc48aa9cf47 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 1015f7d889880..6738017673003 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index e550e5bfcf3c3..5f73ff7d6bd58 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -20,6 +20,7 @@ error: fn_abi_of(test) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -67,6 +68,7 @@ error: fn_abi_of(test) = FnAbi { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -125,6 +127,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -163,6 +166,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -213,6 +217,7 @@ error: fn_abi_of(test_generic) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -248,6 +253,7 @@ error: fn_abi_of(test_generic) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -297,6 +303,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -332,6 +339,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -369,6 +377,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -404,6 +413,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -444,6 +454,7 @@ error: ABIs are not compatible count: 32, }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -483,6 +494,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -517,6 +529,7 @@ error: ABIs are not compatible count: 32, }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -556,6 +569,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -598,6 +612,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -633,6 +648,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -670,6 +686,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -705,6 +722,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -748,6 +766,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -783,6 +802,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -820,6 +840,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -855,6 +876,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -923,6 +945,7 @@ error: fn_abi_of(assoc_test) = FnAbi { valid_range: $NON_NULL, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -960,6 +983,7 @@ error: fn_abi_of(assoc_test) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 781e9b2f4c9d5..ec85030c10686 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 0daf2d3b9e7f2..07cad7766920f 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -31,6 +31,7 @@ error: layout_of(E) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(E) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -69,7 +71,9 @@ error: layout_of(E) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -83,6 +87,7 @@ error: layout_of(E) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 1, }, @@ -136,6 +141,7 @@ error: layout_of(S) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -161,6 +167,7 @@ error: layout_of(U) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -213,6 +220,7 @@ error: layout_of(Result) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -255,6 +263,7 @@ error: layout_of(Result) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -293,6 +302,7 @@ error: layout_of(Result) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -328,6 +338,7 @@ error: layout_of(i32) = Layout { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -353,6 +364,7 @@ error: layout_of(V) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -378,6 +390,7 @@ error: layout_of(W) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -403,6 +416,7 @@ error: layout_of(Y) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -428,6 +442,7 @@ error: layout_of(P1) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -453,6 +468,7 @@ error: layout_of(P2) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -478,6 +494,7 @@ error: layout_of(P3) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -503,6 +520,7 @@ error: layout_of(P4) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -533,6 +551,7 @@ error: layout_of(P5) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -563,6 +582,7 @@ error: layout_of(MaybeUninit) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index 96f0a8c874086..90c06ba1f834e 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -31,6 +31,7 @@ error: layout_of(A) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(A) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -107,6 +109,7 @@ error: layout_of(B) = Layout { valid_range: 255..=255, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -132,6 +135,7 @@ error: layout_of(B) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -183,6 +187,7 @@ error: layout_of(C) = Layout { valid_range: 256..=256, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -208,6 +213,7 @@ error: layout_of(C) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -259,6 +265,7 @@ error: layout_of(P) = Layout { valid_range: 268435456..=268435456, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -284,6 +291,7 @@ error: layout_of(P) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -335,6 +343,7 @@ error: layout_of(T) = Layout { valid_range: 2164260864..=2164260864, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -360,6 +369,7 @@ error: layout_of(T) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index cd9e4c0278150..3bdb9c5c143e4 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -37,6 +37,7 @@ error: layout_of(MissingPayloadField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -78,6 +79,7 @@ error: layout_of(MissingPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -99,6 +101,7 @@ error: layout_of(MissingPayloadField) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -157,6 +160,7 @@ error: layout_of(CommonPayloadField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -199,6 +203,7 @@ error: layout_of(CommonPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -237,6 +242,7 @@ error: layout_of(CommonPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -294,6 +300,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -335,6 +342,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -372,6 +380,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -429,6 +438,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=4, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -486,6 +496,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -507,6 +518,7 @@ error: layout_of(NicheFirst) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -528,6 +540,7 @@ error: layout_of(NicheFirst) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 2, }, @@ -585,6 +598,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=4, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -642,6 +656,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -663,6 +678,7 @@ error: layout_of(NicheSecond) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -684,6 +700,7 @@ error: layout_of(NicheSecond) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 2, }, diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 15a3f6004f50f..1d4e443644826 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -25,6 +25,7 @@ error: layout_of(Aligned1) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -50,6 +51,7 @@ error: layout_of(Aligned1) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -73,6 +75,7 @@ error: layout_of(Aligned1) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -128,6 +131,7 @@ error: layout_of(Aligned2) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -153,6 +157,7 @@ error: layout_of(Aligned2) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -176,6 +181,7 @@ error: layout_of(Aligned2) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 120081d193c69..0c34331856474 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -31,6 +31,7 @@ error: layout_of(A) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(A) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -107,6 +109,7 @@ error: layout_of(B) = Layout { valid_range: 255..=255, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -132,6 +135,7 @@ error: layout_of(B) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -183,6 +187,7 @@ error: layout_of(C) = Layout { valid_range: 256..=256, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -208,6 +213,7 @@ error: layout_of(C) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -259,6 +265,7 @@ error: layout_of(P) = Layout { valid_range: 268435456..=268435456, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -284,6 +291,7 @@ error: layout_of(P) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -335,6 +343,7 @@ error: layout_of(T) = Layout { valid_range: 2164260864..=2164260864, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -360,6 +369,7 @@ error: layout_of(T) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index b6fcc14c063c5..33d2eede22090 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -25,6 +25,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -54,6 +55,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -88,6 +90,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -133,6 +136,7 @@ error: layout_of(MultipleAlignments) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -162,6 +166,7 @@ error: layout_of(MultipleAlignments) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -187,6 +192,7 @@ error: layout_of(MultipleAlignments) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -221,6 +227,7 @@ error: layout_of(MultipleAlignments) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 2, }, @@ -266,6 +273,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -295,6 +303,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -329,6 +338,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { valid_range: 1..=65535, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -374,6 +384,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -407,6 +418,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -441,6 +453,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 8e8f1d159b740..204db30786ee3 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index 2cd0960ce3eec..1fab00bf50c49 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(1 bytes), + size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 8e8f1d159b740..204db30786ee3 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 8e8f1d159b740..204db30786ee3 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index fa08b323dec2a..f852212deb908 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -4,7 +4,15 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(UnivariantU8) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -50,6 +67,7 @@ error: layout_of(UnivariantU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariantsU8) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariantsU8) = Layout { tag_field: 0, variants: [ Layout { - size: Size(1 bytes), + size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariantsU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariantsU8) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 7da8cfd4dbc2d..690592ba0b8da 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -31,6 +31,7 @@ error: layout_of(NonZero) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -69,6 +70,7 @@ error: layout_of((u32) is 1..=) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -105,6 +107,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -134,6 +137,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -174,6 +178,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +221,7 @@ error: layout_of(Option>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -245,6 +251,7 @@ error: layout_of(Option>) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -285,6 +292,7 @@ error: layout_of(Option>) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -336,6 +344,7 @@ error: layout_of(NonZeroU32New) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, From bcfde13d51229e5ba4cb324194561b18e9326680 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 28 Jan 2025 01:29:37 -0600 Subject: [PATCH 22/25] Update check to reflect that non-ZST uninhabited types should not be PassMode::Ignore. --- compiler/rustc_ty_utils/src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2d20ef3d690dd..0ff82f0c256de 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -464,7 +464,7 @@ fn fn_abi_sanity_check<'tcx>( match &arg.mode { PassMode::Ignore => { - assert!(arg.layout.is_zst() || arg.layout.is_uninhabited()); + assert!(arg.layout.is_zst()); } PassMode::Direct(_) => { // Here the Rust type is used to determine the actual ABI, so we have to be very From 58ebf6afdd01d32f9f6d22d2e788c0dc10bc65a5 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Thu, 13 Feb 2025 13:17:39 -0600 Subject: [PATCH 23/25] Add test that uninhabited repr(transparent) type has same function return ABI as wrapped type. Fix codegen of uninhabited PassMode::Indirect return types. Add codegen test for uninhabited PassMode::Indirect return types. Enable optimizations for uninhabited return type codegen test --- compiler/rustc_codegen_ssa/src/mir/block.rs | 28 +++--------- .../uninhabited-transparent-return-abi.rs | 44 +++++++++++++++++++ .../uninhabited-transparent-return-abi.rs | 33 ++++++++++++++ 3 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 tests/codegen/uninhabited-transparent-return-abi.rs create mode 100644 tests/ui/uninhabited/uninhabited-transparent-return-abi.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0620f08fc731b..49074996174a7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{ - self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason, -}; +use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -942,7 +940,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &fn_abi.ret, &mut llargs, Some(intrinsic), - target, ); let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], @@ -998,19 +995,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let mut llargs = Vec::with_capacity(arg_count); - let destination = target.as_ref().map(|&target| { - ( - self.make_return_dest( - bx, - destination, - &fn_abi.ret, - &mut llargs, - None, - Some(target), - ), - target, - ) - }); + + // We still need to call `make_return_dest` even if there's no `target`, since + // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited, + // and `make_return_dest` adds the return-place indirect pointer to `llargs`. + let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None); + let destination = target.map(|target| (return_dest, target)); // Split the rust-call tupled arguments off. let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() { @@ -1813,11 +1803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, intrinsic: Option, - target: Option, ) -> ReturnDest<'tcx, Bx::Value> { - if target.is_none() { - return ReturnDest::Nothing; - } // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { return ReturnDest::Nothing; diff --git a/tests/codegen/uninhabited-transparent-return-abi.rs b/tests/codegen/uninhabited-transparent-return-abi.rs new file mode 100644 index 0000000000000..6e8b1683163ef --- /dev/null +++ b/tests/codegen/uninhabited-transparent-return-abi.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -Copt-level=3 + +// See https://github.com/rust-lang/rust/issues/135802 + +#![crate_type = "lib"] + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +extern "Rust" { + fn opaque() -> NoReturn; + fn opaque_with_arg(rsi: u32) -> NoReturn; +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref +#[no_mangle] +pub fn test_uninhabited_ret_by_ref() { + // CHECK: %_1 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_1) + // CHECK-NEXT: call void @opaque(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_1) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque(); + } +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref_with_arg +#[no_mangle] +pub fn test_uninhabited_ret_by_ref_with_arg(rsi: u32) { + // CHECK: %_2 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_2) + // CHECK-NEXT: call void @opaque_with_arg(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_2, i32 noundef %rsi) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque_with_arg(rsi); + } +} diff --git a/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs new file mode 100644 index 0000000000000..2c2788a3e5642 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs @@ -0,0 +1,33 @@ +//@ run-pass +//@ needs-unwind +// See https://github.com/rust-lang/rust/issues/135802 + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +// Prior to the PR adding this test, this function had a different ABI than +// `fn() -> Large` (on `x86_64-unknown-linux-gnu` at least), so calling it as `fn() -> Large` +// would pass the return place pointer in rdi and `correct` in rsi, but the function +// would expect `correct` in rdi. +fn never(correct: &mut bool) -> NoReturn { + *correct = true; + panic!("catch this") +} + +fn main() { + let mut correct = false; + let never: fn(&mut bool) -> NoReturn = never; + // Safety: `NoReturn` is a `repr(transparent)` wrapper around `Large`, + // so they should be ABI-compatible. + let never: fn(&mut bool) -> Large = unsafe { std::mem::transmute(never) }; + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| never(&mut correct))); + assert!(result.is_err(), "function should have panicked"); + assert!(correct, "function should have stored `true` into `correct`"); +} From 6493cd8699cc6d55a38b5187ff4cc731f969c483 Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:49:18 -0600 Subject: [PATCH 24/25] Adjust LayoutData::uninhabited doc comment. Co-authored-by: Jubilee --- compiler/rustc_abi/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 14a8a57920049..098638b6bcfa7 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1696,8 +1696,8 @@ pub struct LayoutData { pub largest_niche: Option, /// Is this type known to be uninhabted? /// - /// This is separate from BackendRepr, because an uninhabited return type may require special - /// consideration based on its size or other attributes. + /// This is separate from BackendRepr because uninhabited return types can affect ABI, + /// especially in the case of by-pointer struct returns, which allocate stack even when unused. pub uninhabited: bool, pub align: AbiAndPrefAlign, From e3f5db07e0daa833c51c335fa07d87affd8a8bf9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 18 Feb 2025 11:31:38 +0100 Subject: [PATCH 25/25] fine-tune comment --- compiler/rustc_const_eval/src/interpret/validity.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 3667cc84d708e..40dec0cb39e7b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1264,12 +1264,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } - // *After* all of this, check the ABI. We need to check the ABI to handle - // types like `NonNull` where the `Scalar` info is more restrictive than what - // the fields say (`rustc_layout_scalar_valid_range_start`). - // But in most cases, this will just propagate what the fields say, - // and then we want the error to point at the field -- so, first recurse, - // then check ABI. + // *After* all of this, check further information stored in the layout. We need to check + // this to handle types like `NonNull` where the `Scalar` info is more restrictive than what + // the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will + // just propagate what the fields say, and then we want the error to point at the field -- + // so, we first recurse, then we do this check. // // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check