diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a306b494ceced..3ea7902d5712d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -245,6 +245,16 @@ impl ReprOptions { pub fn inhibits_union_abi_opt(&self) -> bool { self.c() } + + /// Ensures two `repr` are equal up to the seed. + pub fn equal_up_to_seed(&self, other: &Self) -> bool { + let ReprOptions { int, align, pack, flags, scalable, field_shuffle_seed: _ } = *self; + int == other.int + && align == other.align + && pack == other.pack + && flags == other.flags + && scalable == other.scalable + } } /// The maximum supported number of lanes in a SIMD vector. diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index b1aca758d64ae..1cd39f5089617 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -76,7 +76,7 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> { } pub(super) fn dcx(&self) -> DiagCtxtHandle<'diag> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } pub(super) fn used_mut_upvars( diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/freebsd.yml b/compiler/rustc_codegen_cranelift/.github/workflows/freebsd.yml index f344113aa7fdf..e0b2bd34631f9 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/freebsd.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/freebsd.yml @@ -34,8 +34,5 @@ jobs: # Disabling incr comp reduces cache size and incr comp doesn't save # as much on CI anyway. export CARGO_BUILD_INCREMENTAL=false - # FIXME(rust-lang/rust#134863) necessary to avoid error when - # dlopening proc macros during compilation of cg_clif. - export LD_STATIC_TLS_EXTRA=4096 # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 ./y.sh test --skip-test test.rust-random/rand diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 88ea75a6b0299..80bbbfe4e9bc1 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -43,27 +43,27 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cranelift-assembler-x64" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25c5b1bb1d86ae68dca1826a1b668b9951056c42e0eef89e35942c7001eb481" +checksum = "a4a59ddc4abd9c5560f4742864b2cd8c19e73c7263f0c866b2c45c2d31587adc" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b052a1fd94b4565697c56f9d358723c7c354feef42a6569081225c1bed6e86" +checksum = "8a8c361cd22fd0fdd8e61af6bfd86ad9c0c62f78b2b1caa2b9e4e97cd8f605fe" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a599e8ffa6a1a118d2dce4809073ad2f2534b1ae1c6d55697b6b8a324446c971" +checksum = "b86c34ae183cf2410318f899648fe1ef6ab9148486e7b938d7b4d814e61dafc9" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -71,18 +71,18 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1ae13182fadc731b1387287b4c6d257b9191fbb7c980ebb2d74c2db74b743e" +checksum = "415f1a12668869e16ac3b66a729fb8cce8bbe6e50e68d1fa0142acd0c9c05f0c" dependencies = [ "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce9c62e5e11d12f4a8f5f939f29899f32002d38193b47491e2539705a1d447e" +checksum = "73eecedc85ffca4f34dbe197c6545c8ade6579a61352457936f53c3bffa6353b" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c29d6b53cfd758dc1a269310fc92199056db03943b9b774b4911cd615e02ad7" +checksum = "66834005198c3e9e3d89cd69cf1541419402ab75250afbeaa3128db6d5254025" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -119,24 +119,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd8cfe23f3349bfa62e06a450cd94cf5f84fbe78556f4df3276534c4b93d834" +checksum = "7e6efaf74077091a2ff41317cc8eb2779264dae4b8a16d955835f3fcda338f52" [[package]] name = "cranelift-control" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f991b4712f21d9502758f7e6cb11746ca2e6186b06c42995eaf31b1e50a9c498" +checksum = "a4258d4ed6ad4e698fe1fec4277b1fcbea6f2a17cb5ec3f04bddfb38ca83d93e" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e24f9c233a43730e22cf42ab0c03f41265e147eca97b3362be01e0da359d7a5" +checksum = "4f016b6f87b1a46a3f5df59b82d88bb352bf2fa6d7868875dfc4d6b65de5242d" dependencies = [ "cranelift-bitset", "wasmtime-internal-core", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61325401051d35ddbf8e2b5d5b5dec8dd54688c9054046b62e76146e61c88a99" +checksum = "b16f2b149dae6ea3886bee931445196d86d8e71b66f7c3b21abe434f77189be8" dependencies = [ "cranelift-codegen", "hashbrown 0.17.0", @@ -157,15 +157,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f71d642812aa70284750719efbd2cc5ad7e7c5e6c43c026b5b0686ce8a6052" +checksum = "f00258ff3d37f52ed731df679205e66175c728846dbde186ee20e93973d12ee7" [[package]] name = "cranelift-jit" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a0f9300c8a5738553a440fe4f25b85f574d5c41b946880dabd47c809f87997" +checksum = "fa063cc98af51fb9090cd40b674503e21bdfa705d2bff75ebf98b79ffc0f598d" dependencies = [ "anyhow", "cranelift-codegen", @@ -184,9 +184,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f723983af35e690c4e2fc160df5d8895bb4a419a54d693367163d781bd830cc" +checksum = "bff0025f1ff6a0470cbd2a61b125f8501311ea9e6c46ed5bb2110ee6710c6a76" dependencies = [ "anyhow", "cranelift-codegen", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c50cffac70c30cc5d0b1d8d287e7712dc76b1181c43697de63d27f38236ddd" +checksum = "4f31eb7e08f31e5bc9c167c35718b0325efa3d4e234e2e9342316e01b18a4b51" dependencies = [ "cranelift-codegen", "libc", @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "430e18f4886ba98f6a7dbb82c86df19f28f27cac417611e5dcc427a7a8decac9" +checksum = "7ca0d86955529d5b9041c4c07745f6ffa42c32326e9f467a834e2b7bd9a9d156" dependencies = [ "anyhow", "cranelift-codegen", @@ -221,9 +221,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5972dc0a5df7ba6f11e8e1654287c40ea1704ca6ce3b76ef54fa58445ee4ad" +checksum = "2e0b67d313f510520f40c1496c3446af0d6b30219d1ba9a4c09c77ec288a561b" [[package]] name = "crc32fast" @@ -379,9 +379,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2c52737737f8609e94f975dee22854a2d5c125772d4b1cf292120f4d45c186" +checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" dependencies = [ "allocator-api2", "bumpalo", @@ -493,9 +493,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "wasmtime-internal-core" -version = "47.0.0" +version = "48.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852f3326264aea590131a422e3ecb33fae3b6695fd67e2e202e2799cd8d27629" +checksum = "2c01c81d781512e17b38c3a76ca9aa2564bc3f9fd8ff6ffc77ba3e1c290d488a" dependencies = [ "hashbrown 0.17.0", "libm", @@ -503,11 +503,10 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "47.0.0" +version = "48.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e537f59b5ab127ca2d421ecbd8728d70bd6cdc9891cec193fb1f594c3309836c" +checksum = "2a09abde04346919af1136a28f344e200685509e28815aef4c39dc08977cc1d8" dependencies = [ - "cfg-if", "libc", "wasmtime-internal-core", "windows-sys 0.61.2", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index cb595332bac61..ca03be20cd100 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.134.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.134.0" } -cranelift-module = { version = "0.134.0" } -cranelift-native = { version = "0.134.0" } -cranelift-jit = { version = "0.134.0", optional = true } -cranelift-object = { version = "0.134.0", default-features = false } +cranelift-codegen = { version = "0.135.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.135.0" } +cranelift-module = { version = "0.135.0" } +cranelift-native = { version = "0.135.0" } +cranelift-jit = { version = "0.135.0", optional = true } +cranelift-object = { version = "0.135.0", default-features = false } target-lexicon = "0.13" gimli = { version = "0.33", default-features = false, features = ["write"] } object = { version = "0.39.1", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" # Uncomment to use an unreleased version of cranelift #[patch.crates-io] -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index c5436cf67c80a..48003ad270e6f 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -66,7 +66,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system |OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)| |---|---|---|---|---| |Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]| -|FreeBSD|✅[^no-rustup][^tls]|❓|❓|❓| +|FreeBSD|✅[^no-rustup]|❓|❓|❓| |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| |Other unixes|❓|❓|❓|❓| |macOS|✅|✅|N/A|N/A| @@ -80,7 +80,6 @@ Not all targets are available as rustup component for nightly. See notes in the [^xcoff]: XCOFF object file format is not supported. [^no-rustup]: Not available as [rustup component for nightly](https://rust-lang.github.io/rustup-components-history/). You can build it yourself. -[^tls]: FreeBSD requires setting `LD_STATIC_TLS_EXTRA=4096` to build cg_clif. In addition you need at least FreeBSD 14. ## Usage diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 71c0523615ff1..3ac7724f8f318 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -252,7 +252,6 @@ fn build_clif_sysroot_for_target( build_cmd.arg("--features").arg("backtrace panic-unwind"); build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.arg("-Zembed-metadata=no"); - build_cmd.arg("-Zbuild-dir-new-layout"); build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); if compiler.target.contains("apple") { diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index c7b61f519d247..5ae76dc1e591e 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -478,6 +478,8 @@ impl<'a> TestRunner<'a> { cmd.arg("--check-cfg=cfg(jit)"); cmd.arg("--check-cfg=cfg(target_has_reliable_f128)"); cmd.arg("--edition=2024"); + // implicitly passed when building inside the rust repo + cmd.arg("-Zforce-unstable-if-unmarked"); cmd.args(args); cmd } diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 5e986201b385c..9a710caae9cd1 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -1,7 +1,6 @@ #![feature( no_core, lang_items, - never_type, extern_types, thread_local, repr_simd, diff --git a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch index 2268ff9cb266e..f821099e68f88 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch @@ -5,83 +5,54 @@ Subject: [PATCH] Disable 128bit atomic operations Cranelift doesn't support them yet --- - library/core/src/panic/unwind_safe.rs | 6 ----- - library/core/src/sync/atomic.rs | 38 --------------------------- - 2 files changed, 44 deletions(-) + library/core/src/panic/unwind_safe.rs | 4 ++-- + library/core/src/sync/atomic.rs | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs -index a60f0799c0e..af056fbf41f 100644 +index bf2e61d..cb82b07 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs -@@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} +@@ -217,7 +217,7 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} #[cfg(target_has_atomic_load_store = "64")] #[stable(feature = "integer_atomics_stable", since = "1.34.0")] impl RefUnwindSafe for crate::sync::atomic::AtomicI64 {} -#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "99069")] --impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} ++#[cfg(false)] + #[unstable(feature = "integer_atomics", issue = "99069")] + impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} - #[cfg(target_has_atomic_load_store = "ptr")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] -@@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} +@@ -236,7 +236,7 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} #[cfg(target_has_atomic_load_store = "64")] #[stable(feature = "integer_atomics_stable", since = "1.34.0")] impl RefUnwindSafe for crate::sync::atomic::AtomicU64 {} -#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "99069")] --impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} ++#[cfg(false)] + #[unstable(feature = "integer_atomics", issue = "99069")] + impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} - #[cfg(target_has_atomic_load_store = "8")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index 8a9a0b5..92ed9a6 100644 +index e676a38..b6a9a3c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -3762,44 +3757,6 @@ atomic_int! { +@@ -3850,7 +3850,7 @@ atomic_int! { 8, u64 AtomicU64 } -#[cfg(any(target_has_atomic_load_store = "128", doc))] --atomic_int! { -- target_has_atomic_load_store = "128", -- target_has_atomic = "128", -- target_has_atomic_primitive_alignment = "128", -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- "i128", -- "#![feature(integer_atomics)]\n\n", -- atomic_min, atomic_max, -- 16, -- i128 AtomicI128 --} ++#[cfg(false)] + atomic_int! { + target_has_atomic_load_store = "128", + target_has_atomic = "128", +@@ -3869,7 +3869,7 @@ atomic_int! { + 16, + i128 AtomicI128 + } -#[cfg(any(target_has_atomic_load_store = "128", doc))] --atomic_int! { -- target_has_atomic_load_store = "128", -- target_has_atomic = "128", -- target_has_atomic_primitive_alignment = "128", -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- "u128", -- "#![feature(integer_atomics)]\n\n", -- atomic_umin, atomic_umax, -- 16, -- u128 AtomicU128 --} - - #[cfg(target_has_atomic_load_store = "ptr")] - macro_rules! atomic_int_ptr_sized { ++#[cfg(false)] + atomic_int! { + target_has_atomic_load_store = "128", + target_has_atomic = "128", -- 2.48.1 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index ea4ff67c93c89..bc8bfacba1923 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-08-19" +channel = "nightly-2026-09-08" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 3885561e94a1e..5a1374fe56e09 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -138,6 +138,7 @@ rm -r tests/run-make/panic-impl-transitive rm tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs rm tests/ui/statics/issue-91050-1.rs rm tests/ui/statics/issue-91050-2.rs +rm -r tests/run-make/locate-panic-runtime # giving different but possibly correct results # ============================================= @@ -157,6 +158,7 @@ rm -r tests/run-make/strip # same rm -r tests/run-make-cargo/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source rm -r tests/run-make-cargo/panic-immediate-abort-works # same rm -r tests/run-make-cargo/panic-immediate-abort-codegen # same +rm -r tests/run-make-cargo/panic-strategies # same rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features rm -r tests/run-make/const-trait-stable-toolchain # same rm -r tests/run-make/print-request-help-stable-unstable # same @@ -174,6 +176,7 @@ rm tests/ui/process/println-with-broken-pipe.rs # same rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort rm -r tests/run-make/used-proc-macro # doesn't work on arm64 for some reason +rm tests/ui/async-await/async-drop/async-drop-async-gen-return-pending.rs # rustc side fnsig issue # bugs in the test suite # ====================== diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index b1cb5f30cbdfe..e2b0035361733 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -415,49 +415,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { - // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp - let mut parts = section_name.as_str().split(','); - let Some(segment_name) = parts.next() else { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", - section_name - )); - }; - let Some(section_name) = parts.next() else { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", - section_name - )); - }; - if section_name.len() > 16 { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: section name bigger than 16 bytes", - section_name - )); - } - let section_type = parts.next().unwrap_or("regular"); - if section_type != "regular" && section_type != "cstring_literals" { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not supported: unsupported section type {}", - section_name, section_type, - )); - } - let _attrs = parts.next(); - if parts.next().is_some() { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: too many components", - section_name - )); - } - // FIXME(bytecodealliance/wasmtime#8901) set S_CSTRING_LITERALS section type when - // cstring_literals is specified - (segment_name, section_name) - } else { - ("", section_name.as_str()) - }; - // FIXME pass correct section flags on Mach-O - data.set_segment_section(segment_name, section_name, 0); + data.set_custom_section(section_name.as_str()); } let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index 4b0260a8abc74..ad0a15bf7f6e5 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -204,7 +204,7 @@ impl UnwindContext { let mut data = DataDescription::new(); data.define(gcc_except_table.writer.into_vec().into_boxed_slice()); - data.set_segment_section("", ".gcc_except_table", 0); + data.set_custom_section(".gcc_except_table"); for reloc in &gcc_except_table.relocs { match reloc.name { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 71fce9e28f120..6d2a353745235 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -23,6 +23,8 @@ extern crate rustc_index; extern crate rustc_log; extern crate rustc_session; extern crate rustc_span; +#[cfg(feature = "jit")] +extern crate rustc_structures; extern crate rustc_symbol_mangling; extern crate rustc_target; diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index 31fae5b4f96b0..a1de6b709cd92 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -145,17 +145,17 @@ pub(super) fn check_lto_allowed(cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>) // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { - dcx.handle().emit_fatal(LtoDisallowed); + dcx.emit_fatal(LtoDisallowed); } else if *crate_type == CrateType::Dylib { if !cgcx.dylib_lto { - dcx.handle().emit_fatal(LtoDylib); + dcx.emit_fatal(LtoDylib); } } else if *crate_type == CrateType::ProcMacro && !cgcx.dylib_lto { - dcx.handle().emit_fatal(LtoProcMacro); + dcx.emit_fatal(LtoProcMacro); } } if cgcx.prefer_dynamic && !cgcx.dylib_lto { - dcx.handle().emit_fatal(DynamicLinkingWithLTO); + dcx.emit_fatal(DynamicLinkingWithLTO); } } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 805c20755d9f7..09d94fdac0260 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -9,7 +9,7 @@ use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; +use rustc_middle::ty::{self, AdtDef, FieldDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::callconv::{ArgAbi, FnAbi}; use tracing::field::Empty; @@ -229,6 +229,48 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) } + /// Determine whether the given types are identical types from the perspective of C. + pub(super) fn identical_c_types(&self, caller_type: Ty<'tcx>, callee_type: Ty<'tcx>) -> bool { + if caller_type == callee_type { + return true; + } + + // C considers two structs to be the same if they have the same name and the same + // fields. We need a similar rules that that e.g. if caller and callee use the "same" + // type from two different versions of the same crate, that call is accepted. + let ty::Adt(caller_adt, caller_args) = caller_type.kind() else { return false }; + let ty::Adt(callee_adt, callee_args) = callee_type.kind() else { return false }; + + if !( + // They must both be structs. + (caller_adt.is_struct() && callee_adt.is_struct()) + // They must have equal `repr`, and it must be `repr(C)`. + && (caller_adt.repr().c() && caller_adt.repr().equal_up_to_seed(&callee_adt.repr())) + // They must have the same name. + && self.tcx.item_name(caller_adt.did()) == self.tcx.item_name(callee_adt.did()) + ) { + return false; + } + + // All fields must have the same names and types as well, where "same type" recursively + // uses this check. + let caller_fields = &caller_adt.non_enum_variant().fields; + let callee_fields = &callee_adt.non_enum_variant().fields; + caller_fields.len() == callee_fields.len() + && caller_fields.iter().zip(callee_fields).all(|(caller_field, callee_field)| { + if caller_field.name != callee_field.name { + return false; // Bail on different name. + } + // Ensure the normalized type is the same. + let normalized_field_ty = |field: &FieldDef, args| { + self.tcx.normalize_erasing_regions(self.typing_env, field.ty(*self.tcx, args)) + }; + let caller_ty = normalized_field_ty(caller_field, caller_args); + let callee_ty = normalized_field_ty(callee_field, callee_args); + self.identical_c_types(caller_ty, callee_ty) + }) + } + /// Check if these two layouts look like they are fn-ABI-compatible. /// (We also compare the `PassMode`, so this doesn't have to check everything. But it turns out /// that only checking the `PassMode` is insufficient.) @@ -252,8 +294,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let caller = unfold(caller)?; let callee = unfold(callee)?; - // Not-quite-so-fast path: if the types are equal now, they are compatible. - if caller.ty == callee.ty { + // Not-quite-so-fast path: if the types are c-equal now, they are compatible. + // FIXME: This is *not* currently guaranteed by our ABI compatibility docs, but it is needed + // for Miri itself when it checks whether shims were called with the right arguments. + // We should eventually put this into the docs as well. + if self.identical_c_types(caller.ty, callee.ty) { return interp_ok(true); } // Now see if these inner types are compatible. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 00057dc503827..ee1422b257566 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -71,6 +71,7 @@ pub enum VarArgCompatible { /// `T` and `U` are definitely not compatible. Incompatible, /// `T` and `U` are corresponding signed and unsigned integer types. + /// This is compatible only if the value can be represented in both types. CastIntTo { source_is_signed: bool }, } @@ -817,18 +818,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// integers of the same size but different signedness, the passed value must be representable /// in both types. fn validate_c_variadic_argument( - &mut self, + &self, arg_mplace: &MPlaceTy<'tcx, M::Provenance>, callee_type: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { let callee_ty = callee_type.ty; let caller_ty = arg_mplace.layout.ty; - // Identical types are clearly compatible. - if caller_ty == callee_ty { - return interp_ok(()); - } - match self.validate_c_variadic_compatible_ty(arg_mplace.layout.ty, callee_type.ty)? { VarArgCompatible::Compatible => interp_ok(()), VarArgCompatible::Incompatible => throw_ub_format!( @@ -866,12 +862,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// - `T` and `U` are both pointers, and their target types are compatible. /// - `T` is a pointer to [`std::ffi::c_void`] and `U` is a pointer to [`i8`] or [`u8`], /// or vice versa. + /// + /// This is designed to match the C rules for variadics, it is incomparable to what we allow in + /// terms of ABI mismatches for regular (fixed) function arguments. pub fn validate_c_variadic_compatible_ty( - &mut self, + &self, caller_type: Ty<'tcx>, callee_type: Ty<'tcx>, ) -> InterpResult<'tcx, VarArgCompatible> { - if caller_type == callee_type { + // FIXME: Accepting two copies of the same repr(C) type as compatible is currently not + // guaranteed by our `VaList::next_arg` docs, but it is needed for Miri itself when it + // checks whether shims were called with the right arguments. We should eventually put this + // into the docs as well. + if self.identical_c_types(caller_type, callee_type) { return interp_ok(VarArgCompatible::Compatible); } @@ -884,7 +887,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let is_c_char = |ty: Ty<'_>| matches!(ty.kind(), ty::Uint(UintTy::U8) | ty::Int(IntTy::I8)); match (caller_type.kind(), callee_type.kind()) { - (ty::RawPtr(caller_target_ty, _), ty::RawPtr(callee_target_ty, _)) => { + // Some types look different but are actually the same for ABI purposes. + (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => { + // E.g. cast between `usize` and `u64` on a 64-bit platform. + interp_ok(VarArgCompatible::Compatible) + } + // C allows different types if... + // - "both types are pointers to qualified or unqualified versions of compatible types" + // - "one type is pointer to qualified or unqualified void and the other is a pointer to a qualified or + // unqualified character type" + // + // As usual for the ABI, we treat references and raw pointers alike. + ( + ty::RawPtr(caller_target_ty, _) | ty::Ref(_, caller_target_ty, _), + ty::RawPtr(callee_target_ty, _) | ty::Ref(_, callee_target_ty, _), + ) => { // In C, types can be qualified by a combination of `const`, `volatile` and // `restrict`. These properties are irrelevant for the ABI, and don't have an // equivalent in rust. @@ -910,16 +927,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } + // - "one type is a signed integer type, the other type is the corresponding unsigned integer type, + // and the value is representable in both types" (ty::Int(_), ty::Uint(_)) => { interp_ok(VarArgCompatible::CastIntTo { source_is_signed: true }) } (ty::Uint(_), ty::Int(_)) => { interp_ok(VarArgCompatible::CastIntTo { source_is_signed: false }) } - (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => { - // E.g. cast between `usize` and `u64` on a 64-bit platform. - interp_ok(VarArgCompatible::Compatible) - } + // - "or, the type of the next argument is nullptr_t and type is a pointer type that has the same + // representation and alignment requirements as a pointer to a character type" + // This one does not have an equivalent form in Rust. _ => interp_ok(VarArgCompatible::Incompatible), } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e4a307a2224d8..c935efe71edc1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -35,7 +35,7 @@ use rustc_data_structures::profiling::{ }; pub use rustc_errors::catch_fatal_errors; use rustc_errors::emitter::stderr_destination; -use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown}; +use rustc_errors::{ColorConfig, DiagCtxt, DiagCtxtHandle, ErrCode, PResult, markdown}; use rustc_feature::find_gated_cfg; // This avoids a false positive with `-Wunused_crate_dependencies`. // `rust_index` isn't used in this crate's code, but it must be named in the @@ -1442,7 +1442,7 @@ pub static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); /// extra_info. /// /// A custom rustc driver can skip calling this to set up a custom ICE hook. -pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) { +pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(DiagCtxtHandle<'_>)) { // If the user has not explicitly overridden "RUST_BACKTRACE", then produce // full backtraces. When a compiler ICE happens, we want to gather // as much information as possible to present in the issue opened @@ -1524,14 +1524,14 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) fn report_ice( info: &panic::PanicHookInfo<'_>, bug_report_url: &str, - extra_info: fn(&DiagCtxt), + extra_info: fn(DiagCtxtHandle<'_>), using_internal_features: &AtomicBool, ) { let emitter = Box::new(rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new( stderr_destination(rustc_errors::ColorConfig::Auto), )); - let dcx = rustc_errors::DiagCtxt::new(emitter); + let dcx = DiagCtxt::new(emitter); let dcx = dcx.handle(); // a .span_bug or .bug call has already printed what @@ -1602,7 +1602,7 @@ fn report_ice( // We don't trust this callback not to panic itself, so run it at the end after we're sure we've // printed all the relevant info. - extra_info(&dcx); + extra_info(dcx); #[cfg(windows)] if env::var("RUSTC_BREAK_ON_ICE").is_ok() { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index d1dc3ab6e9525..2874b85e9b67a 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1345,7 +1345,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { s } - /// See `DiagCtxt::stash_diagnostic` for details. + /// See `DiagCtxtHandle::stash_diagnostic` for details. pub fn stash(mut self, span: Span, key: StashKey) -> Option { let diag = self.take_diag(); self.dcx.stash_diagnostic(span, key, diag) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f868b11ea6fd2..98a5b32e5d902 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -269,6 +269,9 @@ pub struct DelayedBugPanic; /// A `DiagCtxt` deals with errors and other compiler output. /// Certain errors (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. +/// +/// Note: methods should be implemented not on this type but on `DiagCtxtHandle` or +/// `DiagCtxtInner`, whenever possible. pub struct DiagCtxt { inner: Lock, } @@ -281,17 +284,12 @@ pub struct DiagCtxtHandle<'a> { tainted_with_errors: Option<&'a Cell>>, } -impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { - type Target = &'a DiagCtxt; - - fn deref(&self) -> &Self::Target { - &self.dcx - } -} - /// This inner struct exists to keep it all behind a single lock; /// this is done to prevent possible deadlocks in a multi-threaded compiler, /// as well as inconsistent state observation. +/// +/// Note: methods should be implemented not on this type but on `DiagCtxtHandle` whenever possible. +/// Methods on this type should only be used e.g. when the lock is already held. struct DiagCtxtInner { flags: DiagCtxtFlags, @@ -497,20 +495,25 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } + pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { + DiagCtxtHandle { dcx: self, tainted_with_errors: None } + } +} + +impl<'a> DiagCtxtHandle<'a> { pub fn make_silent(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); inner.emitter = Box::new(emitter::SilentEmitter {}); } pub fn set_emitter(&self, emitter: Box) { - self.inner.borrow_mut().emitter = emitter; + self.dcx.inner.borrow_mut().emitter = emitter; } - // This is here to not allow mutation of flags; - // as of this writing it's used in Session::consider_optimizing and - // in tests in rustc_interface. + // This is here to not allow mutation of flags; as of this writing it's used in + // `emit_lint_base` and in tests in `rustc_interface`. pub fn can_emit_warnings(&self) -> bool { - self.inner.borrow_mut().flags.can_emit_warnings + self.dcx.inner.borrow().flags.can_emit_warnings } /// Resets the diagnostic error count as well as the cached emitted diagnostics. @@ -521,7 +524,7 @@ impl DiagCtxt { pub fn reset_err_count(&self) { // Use destructuring so that if a field gets added to `DiagCtxtInner`, it's impossible to // fail to update this method as well. - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); let DiagCtxtInner { flags: _, err_guars, @@ -563,22 +566,16 @@ impl DiagCtxt { *fulfilled_expectations = Default::default(); } - pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self, tainted_with_errors: None } - } - /// Link this to a taintable context so that emitting errors will automatically set /// the `Option` instead of having to do that manually at every error /// emission site. - pub fn taintable_handle<'a>( - &'a self, + pub fn into_taintable( + self, tainted_with_errors: &'a Cell>, ) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) } + DiagCtxtHandle { dcx: self.dcx, tainted_with_errors: Some(tainted_with_errors) } } -} -impl<'a> DiagCtxtHandle<'a> { /// Stashes a diagnostic for possible later improvement in a different, /// later stage of the compiler. Possible actions depend on the diagnostic /// level: @@ -618,7 +615,7 @@ impl<'a> DiagCtxtHandle<'a> { // diagnostic context is dropped and thus delayed bugs are emitted. Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))), DelayedBug => { - return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); + return self.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect => None, @@ -627,7 +624,8 @@ impl<'a> DiagCtxtHandle<'a> { // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. // See the PR for a discussion. - self.inner + self.dcx + .inner .borrow_mut() .stashed_diagnostics .entry(key) @@ -642,9 +640,10 @@ impl<'a> DiagCtxtHandle<'a> { /// error. pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { // FIXME(#120456) - is `swap_remove` correct? - let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( - |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), - )?; + let (diag, guar, _) = + self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), + )?; assert!(!diag.is_error()); assert!(guar.is_none()); Some(Diag::new_diagnostic(self, diag)) @@ -664,7 +663,7 @@ impl<'a> DiagCtxtHandle<'a> { F: FnMut(&mut Diag<'_>), { // FIXME(#120456) - is `swap_remove` correct? - let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); err.map(|(err, guar, _)| { @@ -688,7 +687,7 @@ impl<'a> DiagCtxtHandle<'a> { new_err: Diag<'_>, ) -> ErrorGuaranteed { // FIXME(#120456) - is `swap_remove` correct? - let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let old_err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); match old_err { @@ -705,7 +704,7 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key) && !stashed_diagnostics.is_empty() { @@ -717,13 +716,13 @@ impl<'a> DiagCtxtHandle<'a> { /// Emit all stashed diagnostics. pub fn emit_stashed_diagnostics(&self) -> Option { - self.inner.borrow_mut().emit_stashed_diagnostics() + self.dcx.inner.borrow_mut().emit_stashed_diagnostics() } /// This excludes delayed bugs. #[inline] pub fn err_count(&self) -> usize { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); inner.err_guars.len() + inner.lint_err_guars.len() + inner @@ -738,7 +737,7 @@ impl<'a> DiagCtxtHandle<'a> { /// Like [`DiagCtxtHandle::err_count`], but only counts errors whose recorded /// emitting thread is the calling thread. pub fn err_count_on_current_thread(&self) -> usize { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); let current = std::thread::current().id(); inner.err_guars.iter().filter(|(_, thread)| *thread == current).count() + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count() @@ -756,22 +755,22 @@ impl<'a> DiagCtxtHandle<'a> { /// This excludes lint errors and delayed bugs. Unless absolutely /// necessary, prefer `has_errors` to this method. pub fn has_errors_excluding_lint_errors(&self) -> Option { - self.inner.borrow().has_errors_excluding_lint_errors() + self.dcx.inner.borrow().has_errors_excluding_lint_errors() } /// This excludes delayed bugs. pub fn has_errors(&self) -> Option { - self.inner.borrow().has_errors() + self.dcx.inner.borrow().has_errors() } /// This excludes nothing. Unless absolutely necessary, prefer `has_errors` /// to this method. pub fn has_errors_or_delayed_bugs(&self) -> Option { - self.inner.borrow().has_errors_or_delayed_bugs() + self.dcx.inner.borrow().has_errors_or_delayed_bugs() } pub fn print_error_count(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); // Any stashed diagnostics should have been handled by // `emit_stashed_diagnostics` by now. @@ -869,27 +868,27 @@ impl<'a> DiagCtxtHandle<'a> { /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. pub fn must_teach(&self, code: ErrCode) -> bool { - self.inner.borrow_mut().taught_diagnostics.insert(code) + self.dcx.inner.borrow_mut().taught_diagnostics.insert(code) } pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option { - self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) + self.dcx.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); + self.dcx.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } pub fn emit_timing_section_start(&self, record: TimingRecord) { - self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start); + self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start); } pub fn emit_timing_section_end(&self, record: TimingRecord) { - self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End); + self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End); } pub fn emit_future_breakage_report(&self) { - let inner = &mut *self.inner.borrow_mut(); + let inner = &mut *self.dcx.inner.borrow_mut(); let diags = mem::take(&mut inner.future_breakage_diagnostics); if !diags.is_empty() { inner.emitter.emit_future_breakage_report(diags); @@ -902,7 +901,7 @@ impl<'a> DiagCtxtHandle<'a> { loud: bool, unused_externs: &[&str], ) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); // This "error" is an odd duck. // - It's only produce with JSON output. @@ -930,7 +929,7 @@ impl<'a> DiagCtxtHandle<'a> { /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. #[must_use] pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet { - mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) + mem::take(&mut self.dcx.inner.borrow_mut().fulfilled_expectations) } /// Trigger an ICE if there are any delayed bugs and no hard errors. @@ -938,7 +937,7 @@ impl<'a> DiagCtxtHandle<'a> { /// This will panic if there are any stashed diagnostics. You can call /// `emit_stashed_diagnostics` to emit those before calling `flush_delayed`. pub fn flush_delayed(&self) { - self.inner.borrow_mut().flush_delayed(); + self.dcx.inner.borrow_mut().flush_delayed(); } /// Used when trimmed_def_paths is called and we must produce a diagnostic @@ -946,10 +945,10 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn set_must_produce_diag(&self) { assert!( - self.inner.borrow().must_produce_diag.is_none(), + self.dcx.inner.borrow().must_produce_diag.is_none(), "should only need to collect a backtrace once" ); - self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture()); + self.dcx.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture()); } } @@ -1186,10 +1185,6 @@ impl<'a> DiagCtxtHandle<'a> { } } -// Note: we prefer implementing operations on `DiagCtxt`, rather than -// `DiagCtxtInner`, whenever possible. This minimizes functions where -// `DiagCtxt::foo()` just borrows `inner` and forwards a call to -// `DiagCtxtInner::foo`. impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2e4da8d948f07..618de2c5356d6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -491,7 +491,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn dcx(&self) -> DiagCtxtHandle<'_> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } fn item_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 56fcc72bd9769..ad469ac8f86d3 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -723,7 +723,7 @@ impl<'tcx> InferOk<'tcx, ()> { impl<'tcx> InferCtxt<'tcx> { pub fn dcx(&self) -> DiagCtxtHandle<'_> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } pub fn next_trait_solver(&self) -> bool { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index fb82f694d6f74..049e1ec22e547 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -418,7 +418,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> }, /// ABI-incompatible argument types. AbiMismatchArgument { - /// The index of the argument whose type is wrong. + /// The index of the argument whose type is wrong (starting at index 0). arg_idx: usize, caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx>, diff --git a/library/std/src/sys/sync/futex/unix.rs b/library/std/src/sys/sync/futex/unix.rs index 9291860d4934c..004d8323060e5 100644 --- a/library/std/src/sys/sync/futex/unix.rs +++ b/library/std/src/sys/sync/futex/unix.rs @@ -62,7 +62,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) // absolute time rather than a relative time. libc::syscall( libc::SYS_futex, - futex as *const Atomic, + futex as *const Atomic as *const u32, libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected, timespec.as_ref().map_or(null(), |t| t as *const libc::timespec), @@ -92,7 +92,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) /// On some platforms, this always returns false. #[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wake(futex: &Atomic) -> bool { - let ptr = futex as *const Atomic; + let ptr = futex as *const Atomic as *const u32; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, 1) > 0 } } @@ -100,7 +100,7 @@ pub fn futex_wake(futex: &Atomic) -> bool { /// Wakes up all threads that are waiting on `futex_wait` on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wake_all(futex: &Atomic) { - let ptr = futex as *const Atomic; + let ptr = futex as *const Atomic as *const u32; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, i32::MAX); diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 78b9b2cd8de39..16c3a6434f35a 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -203,7 +203,7 @@ fn main() -> ExitCode { // as simple as moving the call from the hook to main, because `install_ice_hook` doesn't // accept a generic closure. let version_info = rustc_tools_util::get_version_info!(); - dcx.handle().note(format!("Clippy version: {version_info}")); + dcx.note(format!("Clippy version: {version_info}")); }); rustc_driver::catch_with_exit_code(move || { diff --git a/src/tools/miri/src/shims/sig.rs b/src/tools/miri/src/shims/sig.rs index a5da61d633606..e2e01d8ba0aa7 100644 --- a/src/tools/miri/src/shims/sig.rs +++ b/src/tools/miri/src/shims/sig.rs @@ -150,9 +150,19 @@ macro_rules! shim_sig_arg { $this.tcx.types.bool }; ($this:ident, *_) => { + // Pointee types usually don't matter so we allow it to be omitted. // Mutability does not matter for ABI. $this.machine.layouts.mut_raw_ptr.ty }; + ($this:ident, *$($ty:tt)*) => { + // Pointee types matter for varargs so we support explicitly giving them. + // Mutability does not matter for ABI. + rustc_middle::ty::Ty::new_ptr( + *$this.tcx, + shim_sig_arg!($this, $($ty)*), + rustc_middle::mir::Mutability::Mut, + ) + }; ($this:ident, fn(..) -> _) => { // We currently treat fn ptrs as ABI-compatible with data ptrs so we can just use a raw ptr. $this.machine.layouts.const_raw_ptr.ty @@ -208,12 +218,12 @@ fn check_shim_abi<'tcx>( if caller_abi.c_variadic && !callee_abi.c_variadic { throw_ub_format!( - "ABI mismatch: `{link_name}` is a non-variadic function, but the caller is using a variadic signature" + "ABI mismatch: `{link_name}` is a non-variadic function, but the caller is using a c-variadic signature" ); } if !caller_abi.c_variadic && callee_abi.c_variadic { throw_ub_format!( - "ABI mismatch: `{link_name}` is a variadic function, but the caller is using a non-variadic signature" + "ABI mismatch: `{link_name}` is a c-variadic function, but the caller is using a non-variadic signature" ); } @@ -254,7 +264,7 @@ fn check_shim_abi<'tcx>( // Deliberately not `Copy` so that we don't consume the same vararg multiple times accidentally. pub struct Varargs<'tcx, 'a> { args: &'a [OpTy<'tcx>], - /// Number of variadic arguments that have already been taken, for error messages. + /// Number of arguments (variadic and fixed) that have already been taken, for error messages. already_gone: usize, } @@ -299,7 +309,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } if abi.c_variadic { throw_ub_format!( - "calling a non-variadic function with a variadic caller-side signature" + "calling a non-variadic function with a c-variadic caller-side signature" ); } @@ -360,7 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Return arguments. if let Some((fixed, var)) = caller_args.split_first_chunk() { - return interp_ok((fixed, Varargs { args: var, already_gone: 0 })); + return interp_ok((fixed, Varargs { args: var, already_gone: N })); } unreachable!() } @@ -378,20 +388,45 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some((now, tail)) = varargs.args.split_first_chunk::() else { throw_ub_format!( - "not enough variadic arguments for `{fn_name}`: got {}, expected at least {}", + "not enough arguments for `{fn_name}`: got {}, expected at least {}", varargs.already_gone.strict_add(varargs.args.len()), varargs.already_gone.strict_add(N), ) }; for (n, (caller_gave, callee_expected)) in now.iter().zip(tys).enumerate() { - // Check ABI compatibility. This is less strict than `next_arg` but we're also - // not limited to just a few simple types. - let callee_expected = this.layout_of(callee_expected)?; - - // FIXME: check compatibility once - // landed. - let _unused = (n, caller_gave, callee_expected); + // Check ABI compatibility. + let compatible = + this.validate_c_variadic_compatible_ty(caller_gave.layout.ty, callee_expected)?; + match compatible { + VarArgCompatible::Compatible => {} + VarArgCompatible::Incompatible => { + throw_ub_format!( + "incorrect c-variadic argument type for `{fn_name}`: \ + expected argument #{n} to have type `{callee_expected}` but got incompatible type `{caller_ty}`", + n = varargs.already_gone.strict_add(n).strict_add(1), + caller_ty = caller_gave.layout.ty, + ); + } + VarArgCompatible::CastIntTo { source_is_signed } => { + // Check that the value can be represented in the target type. + let size = caller_gave.layout.size; + let scalar = this.read_scalar(caller_gave)?; + if scalar.to_int(size)? < 0 { + throw_ub_format!( + "incorrect c-variadic argument type for `{fn_name}`: \ + argument #{n} has value `{value}_{caller_ty}` which cannot be represented in expected type `{callee_expected}`", + n = varargs.already_gone.strict_add(n).strict_add(1), + caller_ty = caller_gave.layout.ty, + value = if source_is_signed { + scalar.to_int(size)?.to_string() + } else { + scalar.to_uint(size)?.to_string() + } + ) + } + } + } } interp_ok((now, Varargs { args: tail, already_gone: varargs.already_gone.strict_add(N) })) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 427fec0c84405..1ad71d0d8a648 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -460,11 +460,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let o_creat = this.eval_libc_i32("O_CREAT"); if flag & o_creat == o_creat { flag &= !o_creat; - // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but - // C integer promotion rules mean that on the ABI level, it gets passed as `u32` - // (see https://github.com/rust-lang/rust/issues/71915). + // Get the mode. let ([mode], _) = this.check_varargs( - shim_varargs![libc::mode_t], + if this.libc_ty_layout("mode_t").size.bytes() >= 4 { + // `mode_t` is big enough, no C integer promotion. + shim_varargs![libc::mode_t] + } else { + // Types smaller than int get promoted to int + // (see https://github.com/rust-lang/rust/issues/71915). + shim_varargs![i32] + }, varargs, "open(pathname, O_CREAT, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs index ebbaa836007aa..12a4a1b252ad7 100644 --- a/src/tools/miri/src/shims/unix/linux_like/sync.rs +++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs @@ -16,7 +16,7 @@ pub fn futex<'tcx>( dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let ([addr, op, val], varargs) = - ecx.check_varargs(shim_varargs![*_, i32, u32], varargs, "syscall(SYS_futex, ...)")?; + ecx.check_varargs(shim_varargs![*u32, i32, u32], varargs, "syscall(SYS_futex, ...)")?; // See for docs. // The first three arguments (after the syscall number itself) are the same to all futex operations: @@ -52,7 +52,7 @@ pub fn futex<'tcx>( let (timeout, bitset) = if wait_bitset { let ([timeout, uaddr2, bitset], _) = ecx.check_varargs( - shim_varargs![*_, *_, u32], + shim_varargs![*libc::timespec, *u32, u32], varargs, "syscall(SYS_futex, ...)", )?; @@ -62,8 +62,11 @@ pub fn futex<'tcx>( } (timeout, ecx.read_scalar(bitset)?.to_u32()?) } else { - let ([timeout], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "syscall(SYS_futex, ...)")?; + let ([timeout], _) = ecx.check_varargs( + shim_varargs![*libc::timespec], + varargs, + "syscall(SYS_futex, ...)", + )?; (timeout, u32::MAX) }; @@ -199,7 +202,7 @@ pub fn futex<'tcx>( let bitset = if op == futex_wake_bitset { let ([timeout, uaddr2, bitset], _) = ecx.check_varargs( - shim_varargs![*_, *_, u32], + shim_varargs![*libc::timespec, *u32, u32], varargs, "syscall(SYS_futex, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs index ae9b332657463..2260a0342e7e2 100644 --- a/src/tools/miri/src/shims/unix/linux_like/syscall.rs +++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs @@ -37,7 +37,7 @@ pub fn syscall<'tcx>( // Used by getrandom 0.1 // The first argument is the syscall id, so skip over it. let ([ptr, len, flags], _) = ecx.check_varargs( - shim_varargs![*_, usize, i32], + shim_varargs![*libc::c_void, usize, i32], varargs, "syscall(SYS_getrandom, ...)", )?; @@ -70,7 +70,7 @@ pub fn syscall<'tcx>( num if num == sys_accept4 => { // Used on Android. let ([socket, address, address_len, flags], _) = ecx.check_varargs( - shim_varargs![i32, *_, *_, i32], + shim_varargs![i32, *libc::sockaddr, *libc::socklen_t, i32], varargs, "syscall(SYS_accept4, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/thread.rs b/src/tools/miri/src/shims/unix/linux_like/thread.rs index 8ddf122af654f..987de85740ea5 100644 --- a/src/tools/miri/src/shims/unix/linux_like/thread.rs +++ b/src/tools/miri/src/shims/unix/linux_like/thread.rs @@ -26,7 +26,7 @@ pub fn prctl<'tcx>( let res = match ecx.read_scalar(op)?.to_i32()? { op if op == pr_set_name => { let ([name], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_SET_NAME, ...)")?; + ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_SET_NAME, ...)")?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; @@ -39,7 +39,7 @@ pub fn prctl<'tcx>( } op if op == pr_get_name => { let ([name], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_GET_NAME, ...)")?; + ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_GET_NAME, ...)")?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index d0966fab8ab92..d9cc802cd4469 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -208,7 +208,7 @@ impl UnixFileDescription for TcpSocket { ); } - let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*_], args, "ioctl")?; + let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*i32], args, "ioctl")?; let value = ecx.deref_pointer_as(value_ptr, ecx.machine.layouts.i32)?; let non_block = ecx.read_scalar(&value)?.to_i32()? != 0; self.is_non_block.set(non_block); diff --git a/src/tools/miri/src/shims/unix/virtual_socket.rs b/src/tools/miri/src/shims/unix/virtual_socket.rs index a035b56c1e323..04bc2ab8a890a 100644 --- a/src/tools/miri/src/shims/unix/virtual_socket.rs +++ b/src/tools/miri/src/shims/unix/virtual_socket.rs @@ -291,7 +291,7 @@ impl UnixFileDescription for VirtualSocket { ); } - let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*_], args, "ioctl")?; + let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*i32], args, "ioctl")?; let value = ecx.deref_pointer_as(value_ptr, ecx.machine.layouts.i32)?; let non_block = ecx.read_scalar(&value)?.to_i32()? != 0; self.is_nonblock.set(non_block); diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs index 29548c17443a6..2283d3308b935 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs @@ -7,5 +7,5 @@ fn main() { fn test_file_open_missing_needed_mode() { let name = c"missing_arg.txt".as_ptr(); - let _fd = unsafe { libc::open(name, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: not enough variadic arguments + let _fd = unsafe { libc::open(name, libc::O_CREAT) }; //~ ERROR: /Undefined Behavior: not enough arguments.*: got 2/ } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr index 186ca4ccdd406..0ef9d10461127 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: not enough variadic arguments for `open(pathname, O_CREAT, ...)`: got 0, expected at least 1 +error: Undefined Behavior: not enough arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 --> tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs:LL:CC | LL | let _fd = unsafe { libc::open(name, libc::O_CREAT) }; diff --git a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs new file mode 100644 index 0000000000000..3382670b50f18 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs @@ -0,0 +1,18 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +//@normalize-stderr-test: "to have type `(u32|i32)`" -> "to have type `$$TYPE`" + +#![allow(invalid_runtime_symbol_definitions)] + +use std::ffi::{CString, OsStr}; +use std::os::unix::ffi::OsStrExt; + +use libc::open; + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let _fd = unsafe { + open(c_path.as_ptr(), libc::O_CREAT, /* should be mode_t */ 0u64) + //~^ ERROR: /expected argument #3 to have type `(u32|i32)` but got incompatible type `u64`/ + }; +} diff --git a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr new file mode 100644 index 0000000000000..8008844273fd7 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: incorrect c-variadic argument type for `open(pathname, O_CREAT, ...)`: expected argument #3 to have type `$TYPE` but got incompatible type `u64` + --> tests/fail-dep/libc/open_wrong_var_arg_type.rs:LL:CC + | +LL | open(c_path.as_ptr(), libc::O_CREAT, /* should be mode_t */ 0u64) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs new file mode 100644 index 0000000000000..f3a2e64fced5c --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs @@ -0,0 +1,23 @@ +mod somewhere_else { + #[repr(C)] + struct CType { + field: i32, + } + + #[unsafe(no_mangle)] + extern "C" fn work_with_c_type(_x: CType) {} + //~^ERROR: parameter #1 has type somewhere_else::CType passing argument of type CType +} + +// Imagine we import the function from above but we end up with a copy of the type declaration. +// We only accept this if the types are *exactly* the name, including the names of all fields. +#[repr(C)] +struct CType(i32); + +extern "C" { + fn work_with_c_type(_x: CType); +} + +fn main() { + unsafe { work_with_c_type(CType(0)) }; +} diff --git a/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr new file mode 100644 index 0000000000000..6d240c1601021 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: calling a function whose parameter #1 has type somewhere_else::CType passing argument of type CType + --> tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + | +LL | extern "C" fn work_with_c_type(_x: CType) {} + | ^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets + = help: if you think this code should be accepted anyway, please report an issue with Miri + = note: stack backtrace: + 0: somewhere_else::work_with_c_type + at tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + 1: main + at tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs similarity index 85% rename from src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs rename to src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs index bf3d4174dbdb7..ce0c6c289faf0 100644 --- a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs @@ -15,6 +15,6 @@ fn main() { let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); let _fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) - //~^ ERROR: is a variadic function, but the caller is using a non-variadic signature + //~^ ERROR: is a c-variadic function, but the caller is using a non-variadic signature }; } diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr similarity index 74% rename from src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr rename to src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr index 788b499841174..be65cd0068d1f 100644 --- a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr @@ -1,5 +1,5 @@ -error: Undefined Behavior: ABI mismatch: `open` is a variadic function, but the caller is using a non-variadic signature - --> tests/fail/shims/non_vararg_signature_mismatch.rs:LL:CC +error: Undefined Behavior: ABI mismatch: `open` is a c-variadic function, but the caller is using a non-variadic signature + --> tests/fail/shims/vararg_callee_signature_mismatch.rs:LL:CC | LL | open(c_path.as_ptr(), /* value does not matter */ 0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs index 1dc36706e284b..be5f44d988430 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs @@ -9,6 +9,6 @@ extern "C" { fn main() { let mut fds = [-1, -1]; let res = unsafe { pipe(fds.as_mut_ptr()) }; - //~^ ERROR: is a non-variadic function, but the caller is using a variadic signature + //~^ ERROR: is a non-variadic function, but the caller is using a c-variadic signature assert_eq!(res, 0); } diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr index 0405fe0ef7501..98fccde50be13 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: ABI mismatch: `pipe` is a non-variadic function, but the caller is using a variadic signature +error: Undefined Behavior: ABI mismatch: `pipe` is a non-variadic function, but the caller is using a c-variadic signature --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC | LL | let res = unsafe { pipe(fds.as_mut_ptr()) }; diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index 2e45af9e28880..9df436a5b6604 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -42,7 +42,7 @@ fn wake_nobody() { fn wake_dangling() { let futex = Box::new(0); - let ptr: *const i32 = &*futex; + let ptr: *const u32 = &*futex; drop(futex); // Expect error since this is now "unmapped" memory. @@ -55,7 +55,7 @@ fn wake_dangling() { } fn wait_wrong_val() { - let futex: i32 = 123; + let futex: u32 = 123; // Only wait if the futex value is 456. unsafe { @@ -76,7 +76,7 @@ fn wait_wrong_val() { fn wait_timeout() { let start = Instant::now(); - let futex: i32 = 123; + let futex: u32 = 123; // Wait for 100ms, with nobody waking us up early. unsafe { @@ -120,12 +120,12 @@ fn wait_absolute_timeout() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAIT_BITSET, - 123, + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAIT_BITSET, // op + 123, // val &timeout, - 0usize, - u32::MAX, + ptr::null::(), // uaddr2 + u32::MAX, // val3 (bitset) ), -1, ); @@ -181,12 +181,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAKE_BITSET, - 10, // Wake up at most 10 threads. + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAKE_BITSET, // op + 10, // val (max wake up count) ptr::null::(), - 0usize, - 0b1001, // bitset + ptr::null::(), // uaddr2 + 0b1001, // val3 (bitset) ), 0, // Didn't match any thread. ); @@ -196,12 +196,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAKE_BITSET, - 10, // Wake up at most 10 threads. + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAKE_BITSET, // op + 10, // val (max wake up count) ptr::null::(), - 0usize, - 0b0110, // bitset + ptr::null::(), // uaddr2 + 0b0110, // val3 (bitset) ), 1, // Woken up one thread. ); @@ -214,12 +214,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAIT_BITSET, - 0, + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAIT_BITSET, // op + 0, // val ptr::null::(), - 0usize, - 0b0100, // bitset + ptr::null::(), // uaddr2 + 0b0100, // val3 (bitset) ), 0, ); @@ -255,7 +255,7 @@ fn concurrent_wait_wake() { unsafe { let ret = libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), + addr_of!(FUTEX).cast::(), libc::FUTEX_WAIT, HELD, ptr::null::(), @@ -277,7 +277,7 @@ fn concurrent_wait_wake() { FUTEX.store(FREE, Ordering::Relaxed); unsafe { DATA = 1; - libc::syscall(libc::SYS_futex, addr_of!(FUTEX), libc::FUTEX_WAKE, 1); + libc::syscall(libc::SYS_futex, addr_of!(FUTEX).cast::(), libc::FUTEX_WAKE, 1); } t.join().unwrap(); diff --git a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs index d804f3642b1d2..0d764c094d594 100644 --- a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs +++ b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs @@ -24,6 +24,25 @@ impl AssocFn { } } +mod somewhere_else { + #[repr(C)] + struct CType { + field: i32, + } + + #[unsafe(no_mangle)] + extern "C" fn work_with_c_type(_x: CType) {} +} + +// Imagine we import the function from above but we end up with a copy of the type declaration. +#[repr(C)] +struct CType { + field: i32, +} +extern "C" { + fn work_with_c_type(_x: CType); +} + fn main() { // Repeat calls to make sure the `Instance` cache is not broken. for _ in 0..3 { @@ -77,5 +96,7 @@ fn main() { assert_eq!(transmute(qux)(), -4); } } + + unsafe { work_with_c_type(CType { field: 0 }) }; } }