diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b9414df2b86d7..22300fda5f698 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2084,7 +2084,8 @@ impl Niche { let distance_end_zero = max_value - v.end; // FIXME: this ought to work for `bool` too, but that seems to be hitting a miscompilation // - if count == 1 && v != (WrappingRange { start: 0, end: 1 }) { + let is_bool = size.bytes() == 1 && v == WrappingRange { start: 0, end: 1 }; + if count == 1 && !is_bool { // We only need one, so just pick the one closest to zero. // Not only does that obviously use zero if it's possible, but it also // simplifies testing things like `Option`, since looking for `-1` diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 2a7dc8ba10162..11b8890346dfb 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -35,18 +35,18 @@ pub(crate) struct LoweredConstraints<'tcx> { pub(crate) placeholder_indices: PlaceholderIndices<'tcx>, } -impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { - pub(crate) fn init(definitions: &'d IndexVec>) -> Self { - Self { scc_to_annotation: IndexVec::new(), definitions } - } -} - /// A Visitor for SCC annotation construction. pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> { pub(crate) scc_to_annotation: IndexVec, definitions: &'d IndexVec>, } +impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { + pub(crate) fn init(definitions: &'d IndexVec>) -> Self { + Self { scc_to_annotation: IndexVec::new(), definitions } + } +} + impl scc::Annotations for SccAnnotations<'_, '_, RegionTracker> { fn new(&self, element: RegionVid) -> RegionTracker { RegionTracker::new(element, &self.definitions[element]) @@ -118,7 +118,7 @@ impl RegionTracker { } /// The largest universe this SCC can name. It's the smallest - /// largest nameable universe of any reachable region, or + /// max-nameable-universe of any reachable region, or /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)` pub(crate) fn max_nameable_universe(self) -> UniverseIndex { self.max_nameable_universe.0 @@ -208,7 +208,7 @@ pub(super) fn region_definitions<'tcx>( /// graph such that there is a series of constraints /// A: B: C: ... : X where /// A contains a placeholder whose universe cannot be named by X, -/// add a constraint that A: 'static. This is a safe upper bound +/// add a constraint that X: 'static. This is a safe upper bound /// in the face of borrow checker/trait solver limitations that will /// eventually go away. /// @@ -327,8 +327,6 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>( for scc in sccs.all_sccs() { // No point in adding 'static: 'static! - // This micro-optimisation makes somewhat sense - // because static outlives *everything*. if scc == sccs.scc(fr_static) { continue; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5cdda777723b3..2a759387788a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -501,43 +501,48 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut errors_buffer = RegionErrors::new(infcx.tcx); - // If this is a closure, we can propagate unsatisfied - // `outlives_requirements` to our creator, so create a vector - // to store those. Otherwise, we'll pass in `None` to the - // functions below, which will trigger them to report errors - // eagerly. - let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); - debug!(?outlives_requirements); + debug!(?propagated_outlives_requirements); // In Polonius mode, the errors about missing universal region relations are in the output // and need to be emitted or propagated. Otherwise, we need to check whether the // constraints were too strong, and if so, emit or propagate those errors. if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { self.check_polonius_subset_errors( - outlives_requirements.as_mut(), + propagated_outlives_requirements.as_mut(), &mut errors_buffer, polonius_output .as_ref() .expect("Polonius output is unavailable despite `-Z polonius`"), ); } else { - self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer); + self.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); } debug!(?errors_buffer); - let outlives_requirements = outlives_requirements.unwrap_or_default(); + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); - if outlives_requirements.is_empty() { + if propagated_outlives_requirements.is_empty() { (None, errors_buffer) } else { let num_external_vids = self.universal_regions().num_global_and_external_regions(); ( - Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }), + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), errors_buffer, ) } diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 7f9fd0cc7c5e0..a3ab9a91e3a8b 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -242,7 +242,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 if: ${{ github.ref == 'refs/heads/main' }} - needs: [todo_check, rustfmt, test, bench, dist] + # FIXME add bench back once rust-lang/cargo#16925 has been fixed + needs: [todo_check, rustfmt, test, dist] permissions: contents: write # for creating the dev tag and release diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 2d84d2c57fc6b..ca623eabaa2d0 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.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f248321c6a7d4de5dcf2939368e96a397ad3f53b6a076e38d0104d1da326d37" +checksum = "6edb5bdd1af46714e3224a017fabbbd57f70df4e840eb5ad6a7429dc456119d6" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6d78ff1f7d9bf8b7e1afbedbf78ba49e38e9da479d4c8a2db094e22f64e2bc" +checksum = "a819599186e1b1a1f88d464e06045696afc7aa3e0cc018aa0b2999cb63d1d088" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6005ba640213a5b95382aeaf6b82bf028309581c8d7349778d66f27dc1180b" +checksum = "36e2c152d488e03c87b913bc2ed3414416eb1e0d66d61b49af60bf456a9665c7" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -71,18 +71,18 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fb5b134a12b559ff0c0f5af0fcd755ad380723b5016c4e0d36f74d39485340" +checksum = "b6559d4fbc253d1396e1f6beeae57fa88a244f02aaf0cde2a735afd3492d9b2e" dependencies = [ "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85837de8be7f17a4034a6b08816f05a3144345d2091937b39d415990daca28f4" +checksum = "96d9315d98d6e0a64454d4c83be2ee0e8055c3f80c3b2d7bcad7079f281a06ff" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e433faa87d38e5b8ff469e44a26fea4f93e58abd7a7c10bad9810056139700c9" +checksum = "d89c00a88081c55e3087c45bebc77e0cc973de2d7b44ef6a943c7122647b89f5" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -119,24 +119,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5397ba61976e13944ca71230775db13ee1cb62849701ed35b753f4761ed0a9b7" +checksum = "879f77c497a1eb6273482aa1ac3b23cb8563ff04edb39ed5dfcfd28c8deff8f5" [[package]] name = "cranelift-control" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc81c88765580720eb30f4fc2c1bfdb75fcbf3094f87b3cd69cecca79d77a245" +checksum = "498dc1f17a6910c88316d49c7176d8fa97cf10c30859c32a266040449317f963" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463feed5d46cf8763f3ba3045284cf706dd161496e20ec9c14afbb4ba09b9e66" +checksum = "c2acba797f6a46042ce82aaf7680d0c3567fe2001e238db9df649fd104a2727f" dependencies = [ "cranelift-bitset", "wasmtime-internal-core", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c5eca7696c1c04ab4c7ed8d18eadbb47d6cc9f14ec86fe0881bf1d7e97e261" +checksum = "4dca3df1d107d98d88f159ad1d5eaa2d5cdb678b3d5bcfadc6fc83d8ebb448ea" dependencies = [ "cranelift-codegen", "log", @@ -156,15 +156,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1153844610cc9c6da8cf10ce205e45da1a585b7688ed558aa808bbe2e4e6d77" +checksum = "f62dd18116d88bed649871feceda79dad7b59cc685ea8998c2b3e64d0e689602" [[package]] name = "cranelift-jit" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41836de8321b303d3d4188e58cc09c30c7645337342acfcfb363732695cae098" +checksum = "0a4942770ce6662b44d903493d7c5b00f9a986a713a61aae148306eaef21ebd4" dependencies = [ "anyhow", "cranelift-codegen", @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b731f66cb1b69b60a74216e632968ebdbb95c488d26aa1448ec226ae0ffec33e" +checksum = "fb5ca0d214ecee44405ea9f0c65a5318b41ac469e8258fd9fe944e564c1c1b0b" dependencies = [ "anyhow", "cranelift-codegen", @@ -193,9 +193,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97b583fe9a60f06b0464cee6be5a17f623fd91b217aaac99b51b339d19911af" +checksum = "f843b80360d7fdf61a6124642af7597f6d55724cf521210c34af8a1c66daca6e" dependencies = [ "cranelift-codegen", "libc", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9809d2d419cd18f17377f4ce64a7ad22eeda0d042c08833d3796657f1ddebc82" +checksum = "b9d212d15015c374333b11b833111b7c7e686bfaec02385af53611050bce7e9d" dependencies = [ "anyhow", "cranelift-codegen", @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8594dc6bb4860fa8292f1814c76459dbfb933e1978d8222de6380efce45c7cee" +checksum = "090ee5de58c6f17eb5e3a5ae8cf1695c7efea04ec4dd0ecba6a5b996c9bad7dc" [[package]] name = "crc32fast" @@ -277,6 +277,15 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +dependencies = [ + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -285,12 +294,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", ] [[package]] @@ -338,12 +347,12 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "object" -version = "0.38.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" dependencies = [ "crc32fast", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "indexmap", "memchr", ] @@ -482,9 +491,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "wasmtime-internal-core" -version = "43.0.0" +version = "44.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e671917bb6856ae360cb59d7aaf26f1cfd042c7b924319dd06fd380739fc0b2e" +checksum = "816a61a75275c6be435131fc625a4f5956daf24d9f9f59443e81cbef228929b3" dependencies = [ "hashbrown 0.16.1", "libm", @@ -492,9 +501,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "43.0.0" +version = "44.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3112806515fac8495883885eb8dbdde849988ae91fe6beb544c0d7c0f4c9aa" +checksum = "2fd683a94490bf755d016a09697b0955602c50106b1ded97d16983ab2ded9fed" dependencies = [ "cfg-if", "libc", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 6707557f06f75..b775809a50e3a 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.130.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.130.0" } -cranelift-module = { version = "0.130.0" } -cranelift-native = { version = "0.130.0" } -cranelift-jit = { version = "0.130.0", optional = true } -cranelift-object = { version = "0.130.0" } +cranelift-codegen = { version = "0.131.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.131.0" } +cranelift-module = { version = "0.131.0" } +cranelift-native = { version = "0.131.0" } +cranelift-jit = { version = "0.131.0", optional = true } +cranelift-object = { version = "0.131.0" } target-lexicon = "0.13" gimli = { version = "0.33", default-features = false, features = ["write"] } -object = { version = "0.38.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.39.1", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.9.0", optional = true } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 5205ec1e8aaa1..216c87f095533 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -178,9 +178,7 @@ fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget { && !file_name_str.contains("rustc_std_workspace_") && !file_name_str.contains("rustc_demangle") && !file_name_str.contains("rustc_literal_escaper")) - || file_name_str.contains("chalk") - || file_name_str.contains("tracing") - || file_name_str.contains("regex") + || file_name_str.contains("LLVM") { // These are large crates that are part of the rustc-dev component and are not // necessary to run regular programs. @@ -208,9 +206,9 @@ fn build_clif_sysroot_for_triple( apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs)); - // Cleanup the deps dir, but keep build scripts and the incremental cache for faster - // recompilation as they are not affected by changes in cg_clif. - ensure_empty_dir(&build_dir.join("deps")); + // Cleanup the build dir, but keep the incremental cache for faster + // recompilation as it is not affected by changes in cg_clif. + ensure_empty_dir(&build_dir.join("build")); } // Build sysroot @@ -243,6 +241,7 @@ fn build_clif_sysroot_for_triple( build_cmd.arg("--features").arg("backtrace panic-unwind"); build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.arg("-Zno-embed-metadata"); + 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.triple.contains("apple") { @@ -254,7 +253,13 @@ fn build_clif_sysroot_for_triple( } spawn_and_wait(build_cmd); - for entry in fs::read_dir(build_dir.join("deps")).unwrap() { + for entry in fs::read_dir(build_dir.join("build")) + .unwrap() + .flat_map(|entry| entry.unwrap().path().read_dir().unwrap()) + .map(|entry| entry.unwrap().path().join("out")) + .filter(|entry| entry.exists()) + .flat_map(|entry| entry.read_dir().unwrap()) + { let entry = entry.unwrap(); if let Some(ext) = entry.path().extension() { if ext == "d" || ext == "dSYM" || ext == "clif" { diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch new file mode 100644 index 0000000000000..029e493227cd1 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch @@ -0,0 +1,266 @@ +From 2aa88b261ffb51d3f18a4b9d3b79232d7445e5f3 Mon Sep 17 00:00:00 2001 +From: bjorn3 <17426603+bjorn3@users.noreply.github.com> +Date: Thu, 16 Apr 2026 17:29:02 +0200 +Subject: [PATCH] Disable f16 usage in portable-simd + +It is currently broken on x86_64-pc-windows-gnu +--- + Cargo.toml | 8 ++------ + crates/core_simd/src/alias.rs | 10 ---------- + crates/core_simd/src/cast.rs | 3 --- + crates/core_simd/src/lib.rs | 1 - + crates/core_simd/src/ops.rs | 2 +- + crates/core_simd/src/ops/unary.rs | 2 -- + crates/core_simd/src/simd/cmp/eq.rs | 2 +- + crates/core_simd/src/simd/cmp/ord.rs | 2 +- + crates/core_simd/src/simd/num/float.rs | 2 +- + crates/core_simd/src/vector.rs | 7 ------- + crates/core_simd/tests/f16_ops.rs | 10 ---------- + crates/std_float/src/lib.rs | 9 --------- + crates/test_helpers/src/biteq.rs | 2 +- + crates/test_helpers/src/lib.rs | 2 -- + crates/test_helpers/src/subnormals.rs | 2 +- + 15 files changed, 8 insertions(+), 56 deletions(-) + delete mode 100644 crates/core_simd/tests/f16_ops.rs + +diff --git a/Cargo.toml b/Cargo.toml +index 883140b..45296b4 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -1,10 +1,6 @@ + [workspace] + resolver = "1" +-members = [ +- "crates/core_simd", +- "crates/std_float", +- "crates/test_helpers", +-] ++members = ["crates/core_simd", "crates/std_float", "crates/test_helpers"] + + [profile.test.package."*"] + opt-level = 2 +@@ -15,4 +11,4 @@ opt-level = 2 + [workspace.dependencies.proptest] + version = "1.11" + default-features = false +-features = ["alloc", "f16"] ++features = ["alloc"] +diff --git a/crates/core_simd/src/alias.rs b/crates/core_simd/src/alias.rs +index 6dcfcb6..23f121c 100644 +--- a/crates/core_simd/src/alias.rs ++++ b/crates/core_simd/src/alias.rs +@@ -153,16 +153,6 @@ alias! { + usizex64 64 + } + +- f16 = { +- f16x1 1 +- f16x2 2 +- f16x4 4 +- f16x8 8 +- f16x16 16 +- f16x32 32 +- f16x64 64 +- } +- + f32 = { + f32x1 1 + f32x2 2 +diff --git a/crates/core_simd/src/cast.rs b/crates/core_simd/src/cast.rs +index 69dc7ba..1c3592f 100644 +--- a/crates/core_simd/src/cast.rs ++++ b/crates/core_simd/src/cast.rs +@@ -44,9 +44,6 @@ impl SimdCast for u64 {} + unsafe impl Sealed for usize {} + impl SimdCast for usize {} + // Safety: primitive number types can be cast to other primitive number types +-unsafe impl Sealed for f16 {} +-impl SimdCast for f16 {} +-// Safety: primitive number types can be cast to other primitive number types + unsafe impl Sealed for f32 {} + impl SimdCast for f32 {} + // Safety: primitive number types can be cast to other primitive number types +diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs +index 413a886..115be44 100644 +--- a/crates/core_simd/src/lib.rs ++++ b/crates/core_simd/src/lib.rs +@@ -1,7 +1,6 @@ + #![no_std] + #![feature( + convert_float_to_int, +- f16, + core_intrinsics, + decl_macro, + repr_simd, +diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs +index c0a06ed..eb6601f 100644 +--- a/crates/core_simd/src/ops.rs ++++ b/crates/core_simd/src/ops.rs +@@ -245,7 +245,7 @@ for_base_ops! { + // We don't need any special precautions here: + // Floats always accept arithmetic ops, but may become NaN. + for_base_ops! { +- T = (f16, f32, f64); ++ T = (f32, f64); + type Lhs = Simd; + type Rhs = Simd; + type Output = Self; +diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs +index af7aa8a..e1c0616 100644 +--- a/crates/core_simd/src/ops/unary.rs ++++ b/crates/core_simd/src/ops/unary.rs +@@ -19,8 +19,6 @@ macro_rules! neg { + } + + neg! { +- impl Neg for Simd +- + impl Neg for Simd + + impl Neg for Simd +diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs +index 7683640..d553d6c 100644 +--- a/crates/core_simd/src/simd/cmp/eq.rs ++++ b/crates/core_simd/src/simd/cmp/eq.rs +@@ -42,7 +42,7 @@ macro_rules! impl_number { + } + } + +-impl_number! { f16, f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } ++impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } + + macro_rules! impl_mask { + { $($integer:ty),* } => { +diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs +index 5a4e74c..5672fbb 100644 +--- a/crates/core_simd/src/simd/cmp/ord.rs ++++ b/crates/core_simd/src/simd/cmp/ord.rs +@@ -144,7 +144,7 @@ macro_rules! impl_float { + } + } + +-impl_float! { f16, f32, f64 } ++impl_float! { f32, f64 } + + macro_rules! impl_mask { + { $($integer:ty),* } => { +diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs +index 510f4c9..175cbce 100644 +--- a/crates/core_simd/src/simd/num/float.rs ++++ b/crates/core_simd/src/simd/num/float.rs +@@ -444,4 +444,4 @@ macro_rules! impl_trait { + } + } + +-impl_trait! { f16 { bits: u16, mask: i16 }, f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } ++impl_trait! { f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } +diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs +index fbef69f..c8e0b8c 100644 +--- a/crates/core_simd/src/vector.rs ++++ b/crates/core_simd/src/vector.rs +@@ -1146,13 +1146,6 @@ unsafe impl SimdElement for isize { + type Mask = isize; + } + +-impl Sealed for f16 {} +- +-// Safety: f16 is a valid SIMD element type, and is supported by this API +-unsafe impl SimdElement for f16 { +- type Mask = i16; +-} +- + impl Sealed for f32 {} + + // Safety: f32 is a valid SIMD element type, and is supported by this API +diff --git a/crates/core_simd/tests/f16_ops.rs b/crates/core_simd/tests/f16_ops.rs +deleted file mode 100644 +index f89bdf4..0000000 +--- a/crates/core_simd/tests/f16_ops.rs ++++ /dev/null +@@ -1,10 +0,0 @@ +-#![feature(portable_simd)] +-#![feature(f16)] +- +-#[macro_use] +-mod ops_macros; +- +-// FIXME: some f16 operations cause rustc to hang on wasm simd +-// https://github.com/llvm/llvm-project/issues/189251 +-#[cfg(not(all(target_arch = "wasm32", target_feature = "simd128")))] +-impl_float_tests! { f16, i16 } +diff --git a/crates/std_float/src/lib.rs b/crates/std_float/src/lib.rs +index ff35254..acc1bfc 100644 +--- a/crates/std_float/src/lib.rs ++++ b/crates/std_float/src/lib.rs +@@ -2,7 +2,6 @@ + feature = "as_crate", + feature(core_intrinsics), + feature(portable_simd), +- feature(f16), + allow(internal_features) + )] + #[cfg(not(feature = "as_crate"))] +@@ -170,17 +169,9 @@ pub trait StdFloat: Sealed + Sized { + fn fract(self) -> Self; + } + +-impl Sealed for Simd {} + impl Sealed for Simd {} + impl Sealed for Simd {} + +-impl StdFloat for Simd { +- #[inline] +- fn fract(self) -> Self { +- self - self.trunc() +- } +-} +- + impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { +diff --git a/crates/test_helpers/src/biteq.rs b/crates/test_helpers/src/biteq.rs +index 36761e3..cbc20cd 100644 +--- a/crates/test_helpers/src/biteq.rs ++++ b/crates/test_helpers/src/biteq.rs +@@ -53,7 +53,7 @@ macro_rules! impl_float_biteq { + }; + } + +-impl_float_biteq! { f16, f32, f64 } ++impl_float_biteq! { f32, f64 } + + impl BitEq for *const T { + fn biteq(&self, other: &Self) -> bool { +diff --git a/crates/test_helpers/src/lib.rs b/crates/test_helpers/src/lib.rs +index 82adb06..4b03674 100644 +--- a/crates/test_helpers/src/lib.rs ++++ b/crates/test_helpers/src/lib.rs +@@ -1,4 +1,3 @@ +-#![feature(f16)] + #![cfg_attr( + any(target_arch = "powerpc", target_arch = "powerpc64"), + feature(powerpc_target_feature, stdarch_powerpc) +@@ -47,7 +46,6 @@ impl_num! { u16 } + impl_num! { u32 } + impl_num! { u64 } + impl_num! { usize } +-impl_num! { f16 } + impl_num! { f32 } + impl_num! { f64 } + +diff --git a/crates/test_helpers/src/subnormals.rs b/crates/test_helpers/src/subnormals.rs +index 44dfbb3..b5f19ba 100644 +--- a/crates/test_helpers/src/subnormals.rs ++++ b/crates/test_helpers/src/subnormals.rs +@@ -39,7 +39,7 @@ macro_rules! impl_else { + } + } + +-impl_float! { f16, f32, f64 } ++impl_float! { f32, f64 } + impl_else! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } + + /// AltiVec should flush subnormal inputs to zero, but QEMU seems to only flush outputs. +-- +2.53.0 + diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index d4bb9bea82bb5..486078185db84 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-03-25" +channel = "nightly-2026-04-28" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 2ca0c3cab910f..7ce54a45e2ce6 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -67,9 +67,9 @@ index bc68bfe396..00143ef3ed 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2230,7 +2230,7 @@ pub fn download_ci_rustc_commit<'a>( - return None; - } - + match freshness { + PathFreshness::LastModifiedUpstream { upstream } => upstream, + PathFreshness::HasLocalModifications { upstream, modifications } => { - if dwn_ctx.is_running_on_ci() { + if false && dwn_ctx.is_running_on_ci() { eprintln!("CI rustc commit matches with HEAD and we are in CI."); diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 71ff4eef071c3..0b7e308b9489f 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -50,6 +50,7 @@ rm tests/ui/c-variadic/copy.rs # same rm tests/ui/sanitizer/kcfi-c-variadic.rs # same rm tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs # variadics for calling conventions other than C unsupported rm tests/ui/delegation/fn-header.rs +rm tests/ui/c-variadic/roundtrip.rs # inline assembly features rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly @@ -144,6 +145,7 @@ rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift rm -r tests/run-make/short-ice # ICE backtrace begin/end marker mismatch +rm -r tests/run-make/naked-dead-code-elimination # function not eliminated # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended diff --git a/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs b/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs index d8977657e305d..e63e4bebf78a2 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_f16_f128.rs @@ -51,6 +51,40 @@ fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } } +// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have +// been added to Cranelift. +pub(crate) fn maybe_with_f16_to_f32( + fx: &mut FunctionCx<'_, '_, '_>, + val: Value, + f: impl FnOnce(&mut FunctionCx<'_, '_, '_>, Value) -> Value, +) -> Value { + if fx.bcx.func.dfg.value_type(val) == types::F16 { + let val = f16_to_f32(fx, val); + let res = f(fx, val); + f32_to_f16(fx, res) + } else { + f(fx, val) + } +} + +// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have +// been added to Cranelift. +pub(crate) fn maybe_with_f16_to_f32_pair( + fx: &mut FunctionCx<'_, '_, '_>, + a: Value, + b: Value, + f: impl FnOnce(&mut FunctionCx<'_, '_, '_>, Value, Value) -> Value, +) -> Value { + if fx.bcx.func.dfg.value_type(a) == types::F16 { + let a = f16_to_f32(fx, a); + let b = f16_to_f32(fx, b); + let res = f(fx, a, b); + f32_to_f16(fx, res) + } else { + f(fx, a, b) + } +} + pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs: Value) -> Value { let ty = fx.bcx.func.dfg.value_type(lhs); match ty { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs index 8016c5a3005a2..cc1efef287517 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs @@ -43,7 +43,7 @@ impl DebugContext { let _: Result<()> = sections.for_each(|id, section| { if let Some(section_id) = section_map.get(&id) { for reloc in §ion.relocs { - product.add_debug_reloc(§ion_map, section_id, reloc); + product.add_debug_reloc(§ion_map, section_id, reloc, true); } } Ok(()) diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs index 1c6e471cc870f..0af03ff33a43e 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs @@ -1,7 +1,7 @@ use cranelift_module::{DataId, FuncId}; use cranelift_object::ObjectProduct; use gimli::SectionId; -use object::write::{Relocation, StandardSegment}; +use object::write::{Relocation, StandardSection, StandardSegment}; use object::{RelocationEncoding, RelocationFlags, SectionKind}; use rustc_data_structures::fx::FxHashMap; @@ -16,6 +16,7 @@ pub(super) trait WriteDebugInfo { section_map: &FxHashMap, from: &Self::SectionId, reloc: &DebugReloc, + use_section_symbol: bool, ); } @@ -27,29 +28,31 @@ impl WriteDebugInfo for ObjectProduct { id: SectionId, data: Vec, ) -> (object::write::SectionId, object::write::SymbolId) { - let name = if self.object.format() == object::BinaryFormat::MachO { - id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info + let (section_id, align); + if id == SectionId::EhFrame { + section_id = self.object.section_id(StandardSection::EhFrame); + align = 8; } else { - id.name().to_string() - } - .into_bytes(); - - let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); - // FIXME use SHT_X86_64_UNWIND for .eh_frame - let section_id = self.object.add_section( - segment, - name, - if id == SectionId::DebugStr || id == SectionId::DebugLineStr { - SectionKind::DebugString - } else if id == SectionId::EhFrame { - SectionKind::ReadOnlyData + let name = if self.object.format() == object::BinaryFormat::MachO { + id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info } else { - SectionKind::Debug - }, - ); - self.object - .section_mut(section_id) - .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 }); + id.name().to_string() + } + .into_bytes(); + + let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); + section_id = self.object.add_section( + segment, + name, + if id == SectionId::DebugStr || id == SectionId::DebugLineStr { + SectionKind::DebugString + } else { + SectionKind::Debug + }, + ); + align = 1; + } + self.object.section_mut(section_id).set_data(data, align); let symbol_id = self.object.section_symbol(section_id); (section_id, symbol_id) } @@ -59,6 +62,7 @@ impl WriteDebugInfo for ObjectProduct { section_map: &FxHashMap, from: &Self::SectionId, reloc: &DebugReloc, + use_section_symbol: bool, ) { let (symbol, symbol_offset) = match reloc.name { DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0), @@ -69,7 +73,11 @@ impl WriteDebugInfo for ObjectProduct { } else { self.data_symbol(DataId::from_u32(id & !(1 << 31))) }; - self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0)) + if use_section_symbol { + self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0)) + } else { + (symbol_id, 0) + } } }; self.object diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index 33ffe4cc4e9c8..1ce424332db20 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -120,13 +120,12 @@ impl UnwindContext { func_id: FuncId, context: &Context, ) { - if let target_lexicon::OperatingSystem::MacOSX { .. } = - module.isa().triple().operating_system + let triple = module.isa().triple(); + if matches!(triple.operating_system, target_lexicon::OperatingSystem::MacOSX { .. }) + && triple.architecture == target_lexicon::Architecture::X86_64 { // The object crate doesn't currently support DW_GNU_EH_PE_absptr, which macOS - // requires for unwinding tables. In addition on arm64 it currently doesn't - // support 32bit relocations as we currently use for the unwinding table. - // See gimli-rs/object#415 and rust-lang/rustc_codegen_cranelift#1371 + // requires for unwinding tables. See gimli-rs/object#415. return; } @@ -250,8 +249,9 @@ impl UnwindContext { let mut section_map = FxHashMap::default(); section_map.insert(id, section_id); + let use_section_symbol = product.object.format() != object::BinaryFormat::MachO; for reloc in &eh_frame.0.relocs { - product.add_debug_reloc(§ion_map, §ion_id, reloc); + product.add_debug_reloc(§ion_map, §ion_id, reloc, use_section_symbol); } } } diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 9bbc338a8e07c..3903e6ea3b1da 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -7,7 +7,7 @@ use std::os::raw::{c_char, c_int}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::MonoItem; +use rustc_middle::mono::MonoItem; use rustc_session::Session; use rustc_session::config::OutputFilenames; use rustc_span::sym; diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index b14988577845f..5765601763e44 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -235,6 +235,9 @@ pub(crate) fn compile_global_asm( .arg("-") .arg("-Abad_asm_style") .arg("-Zcodegen-backend=llvm") + // JSON targets currently require `-Zunstable-options` + // Tracking issue: https://github.com/rust-lang/rust/issues/151528 + .arg("-Zunstable-options") .stdin(Stdio::piped()) .spawn() .expect("Failed to spawn `as`."); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 780550fc4cc74..95c47715d19df 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1197,12 +1197,9 @@ fn codegen_regular_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - // FIXME(bytecodealliance/wasmtime#8312): Use `fmin` directly once - // Cranelift backend lowerings are implemented. - let a = codegen_f16_f128::f16_to_f32(fx, a); - let b = codegen_f16_f128::f16_to_f32(fx, b); - let val = fx.bcx.ins().fmin(a, b); - let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmin(a, b) + }); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); ret.write_cvalue(fx, val); } @@ -1240,12 +1237,9 @@ fn codegen_regular_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - // FIXME(bytecodealliance/wasmtime#8312): Use `fmax` directly once - // Cranelift backend lowerings are implemented. - let a = codegen_f16_f128::f16_to_f32(fx, a); - let b = codegen_f16_f128::f16_to_f32(fx, b); - let val = fx.bcx.ins().fmax(a, b); - let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmax(a, b) + }); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); ret.write_cvalue(fx, val); } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index cc2311a67b5d5..b8e1886b2d3c1 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -91,23 +91,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual, x_lane, y_lane) } + // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift + // `fcmp` once `f16`/`f128` backend lowerings have been added to + // Cranelift. (ty::Float(_), sym::simd_eq) => { - fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::Equal, x_lane, y_lane) } (ty::Float(_), sym::simd_ne) => { - fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::NotEqual, x_lane, y_lane) } (ty::Float(_), sym::simd_lt) => { - fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::LessThan, x_lane, y_lane) } (ty::Float(_), sym::simd_le) => { - fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::LessThanOrEqual, x_lane, y_lane) } (ty::Float(_), sym::simd_gt) => { - fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::GreaterThan, x_lane, y_lane) } (ty::Float(_), sym::simd_ge) => { - fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::GreaterThanOrEqual, x_lane, y_lane) } _ => unreachable!(), @@ -391,6 +394,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( intrinsic, ) { (ty::Int(_), sym::simd_neg) => fx.bcx.ins().ineg(lane), + (ty::Float(FloatTy::F16), sym::simd_neg) => codegen_f16_f128::neg_f16(fx, lane), (ty::Float(_), sym::simd_neg) => fx.bcx.ins().fneg(lane), (ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8), sym::simd_bswap) => lane, @@ -418,50 +422,65 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // FIXME use vector instructions when possible simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { - match (lane_ty.kind(), intrinsic) { - (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), - (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), - - (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), - (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), - - (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), - (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), - (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), - (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), - (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( - "fmodf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[x_lane, y_lane], - )[0], - (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( - "fmod", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[x_lane, y_lane], - )[0], - - (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), - (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), - (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - _ => unreachable!(), - } + codegen_f16_f128::maybe_with_f16_to_f32_pair( + fx, + x_lane, + y_lane, + |fx, x_lane, y_lane| match (lane_ty.kind(), intrinsic) { + (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), + (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), + + (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), + (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), + + (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), + (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), + (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), + (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), + (ty::Float(FloatTy::F16), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + // FIXME(bytecodealliance/wasmtime#8312): Already converted + // by the FIXME above. + // fx.bcx.ins().fpromote(types::F32, lhs), + // fx.bcx.ins().fpromote(types::F32, rhs), + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( + "fmod", + vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[x_lane, y_lane], + )[0], + + (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), + (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), + (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + _ => unreachable!(), + }, + ) }); } @@ -486,7 +505,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let b_lane = b.value_lane(fx, lane).load_scalar(fx); let c_lane = c.value_lane(fx, lane).load_scalar(fx); - let res_lane = fx.bcx.ins().fma(a_lane, b_lane, c_lane); + let res_lane = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + codegen_f16_f128::fma_f16(fx, a_lane, b_lane, c_lane) + } else { + fx.bcx.ins().fma(a_lane, b_lane, c_lane) + }; let res_lane = CValue::by_val(res_lane, res_lane_layout); ret.place_lane(fx, lane).write_cvalue(fx, res_lane); @@ -584,14 +607,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } - match intrinsic { + + codegen_f16_f128::maybe_with_f16_to_f32(fx, lane, |fx, lane| match intrinsic { sym::simd_fabs => fx.bcx.ins().fabs(lane), sym::simd_fsqrt => fx.bcx.ins().sqrt(lane), sym::simd_ceil => fx.bcx.ins().ceil(lane), sym::simd_floor => fx.bcx.ins().floor(lane), sym::simd_trunc => fx.bcx.ins().trunc(lane), _ => unreachable!(), - } + }) }); } @@ -607,7 +631,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fadd(a, b) + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fadd(a, b) + }) } else { fx.bcx.ins().iadd(a, b) } @@ -625,7 +651,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fadd(a, b) + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fadd(a, b) + }) } else { fx.bcx.ins().iadd(a, b) } @@ -644,7 +672,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fmul(a, b) + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmul(a, b) + }) } else { fx.bcx.ins().imul(a, b) } @@ -662,7 +692,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fmul(a, b) + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmul(a, b) + }) } else { fx.bcx.ins().imul(a, b) } diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index e583f3f2f754a..e533c0b631b01 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -358,7 +358,6 @@ pub(crate) fn codegen_float_binop<'tcx>( } else { (lhs, rhs) }; - let b = fx.bcx.ins(); let res = match bin_op { // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings // have been added to Cranelift. @@ -367,10 +366,10 @@ pub(crate) fn codegen_float_binop<'tcx>( { codegen_f16_f128::codegen_f128_binop(fx, bin_op, lhs, rhs) } - BinOp::Add => b.fadd(lhs, rhs), - BinOp::Sub => b.fsub(lhs, rhs), - BinOp::Mul => b.fmul(lhs, rhs), - BinOp::Div => b.fdiv(lhs, rhs), + BinOp::Add => fx.bcx.ins().fadd(lhs, rhs), + BinOp::Sub => fx.bcx.ins().fsub(lhs, rhs), + BinOp::Mul => fx.bcx.ins().fmul(lhs, rhs), + BinOp::Div => fx.bcx.ins().fdiv(lhs, rhs), BinOp::Rem => { let (name, ty, lhs, rhs) = match in_lhs.layout().ty.kind() { ty::Float(FloatTy::F16) => ( @@ -389,22 +388,12 @@ pub(crate) fn codegen_float_binop<'tcx>( _ => bug!(), }; - let ret_val = fx.lib_call( + fx.lib_call( name, vec![AbiParam::new(ty), AbiParam::new(ty)], vec![AbiParam::new(ty)], &[lhs, rhs], - )[0]; - - let ret_val = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, ret_val) - } else { - ret_val - }; - return CValue::by_val(ret_val, in_lhs.layout()); + )[0] } BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { let fltcc = match bin_op { diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 65779b38ad1c0..918fe3d2a3895 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -60,7 +60,6 @@ use std::fmt; use std::io::Write; use cranelift_codegen::entity::SecondaryMap; -use cranelift_codegen::ir::Fact; use cranelift_codegen::ir::entities::AnyEntity; use cranelift_codegen::write::{FuncWriter, PlainWriter}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -182,13 +181,8 @@ impl FuncWriter for &'_ CommentWriter { _func: &Function, entity: AnyEntity, value: &dyn fmt::Display, - maybe_fact: Option<&Fact>, ) -> fmt::Result { - if let Some(fact) = maybe_fact { - write!(w, " {} ! {} = {}", entity, fact, value)?; - } else { - write!(w, " {} = {}", entity, value)?; - } + write!(w, " {} = {}", entity, value)?; if let Some(comment) = self.entity_comments.get(&entity) { writeln!(w, " ; {}", comment.replace('\n', "\n; ")) diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 67adbaf028eb9..1d9dcdab4ced9 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -204,7 +204,9 @@ impl<'tcx> CValue<'tcx> { let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field); CValue::by_ref(field_ptr, field_layout) } - CValueInner::ByRef(_, Some(_)) => todo!(), + CValueInner::ByRef(_, Some(_)) => { + bug!("value_field for unsized by-ref value not supported") + } } } @@ -655,7 +657,13 @@ impl<'tcx> CPlace<'tcx> { flags, ); } - CValueInner::ByRef(_, Some(_)) => todo!(), + CValueInner::ByRef(_from_ptr, Some(_extra)) => { + bug!( + "write_cvalue for unsized by-ref value not allowed: dst={:?} src={:?}", + dst_layout.ty, + from.layout().ty + ); + } } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3e373c42eca34..9ecf5afcbcb35 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2350,6 +2350,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; + pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 180559d28d848..e9983d11c127f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -480,6 +480,10 @@ pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { match req.kind { PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out), PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out), + PrintKind::BackendHasMnemonic => { + let mnemonic = req.arg.as_deref().expect("BackendHasMnemonic requires arg"); + print_target_has_mnemonic(tm.raw(), mnemonic, out) + } _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } @@ -738,3 +742,10 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } + +fn print_target_has_mnemonic(tm: &llvm::TargetMachine, mnemonic: &str, out: &mut String) { + use std::fmt::Write; + let cstr = SmallCStr::new(mnemonic); + let has_mnemonic = unsafe { llvm::LLVMRustTargetHasMnemonic(tm, cstr.as_ptr()) }; + writeln!(out, "{}", has_mnemonic).unwrap(); +} diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 3f12e857391b2..9b9fa737d6d8d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -217,12 +217,10 @@ fn create_mingw_dll_import_lib( // able to control the *exact* spelling of each of the symbols that are being imported: // hence we don't want `dlltool` adding leading underscores automatically. let dlltool = find_binutils_dlltool(sess); - let temp_prefix = { - let mut path = PathBuf::from(&output_path); - path.pop(); - path.push(lib_name); - path - }; + // temp_prefix doesn't handle paths with spaces so + // use a relative path and set the current working directory + let cwd = output_path.parent().unwrap_or(output_path); + let temp_prefix = lib_name; // dlltool target architecture args from: // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch { @@ -246,7 +244,8 @@ fn create_mingw_dll_import_lib( .arg(dlltool_target_bitness) .arg("--no-leading-underscore") .arg("--temp-prefix") - .arg(temp_prefix); + .arg(temp_prefix) + .current_dir(cwd); match dlltool_cmd.output() { Err(e) => { diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 10abfd7a55ced..c04688e0a49fa 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -27,7 +27,7 @@ mod tests; /// the max/min element of the SCC, or all of the above. /// /// Concretely, the both merge operations must commute, e.g. where `merge` -/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)` +/// is `update_scc` and `update_reachable`: `a.merge(b) == b.merge(a)` /// /// In general, what you want is probably always min/max according /// to some ordering, potentially with side constraints (min x such diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c15c3c229398c..b05f5bc4a8e20 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -804,6 +804,9 @@ fn print_crate_info( let calling_conventions = rustc_abi::all_names(); println_info!("{}", calling_conventions.join("\n")); } + BackendHasMnemonic => { + codegen_backend.print(req, &mut crate_info, sess); + } BackendHasZstd => { let has_zstd: bool = codegen_backend.has_zstd(); println_info!("{has_zstd}"); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 726f05e36ac9f..c7e8f99465e18 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/LTO/LTO.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" @@ -94,6 +95,25 @@ extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, return MCInfo->checkFeatures(std::string("+") + Feature); } +/// Check whether the target has a specific assembly mnemonic like `ret` or +/// `nop`. +/// This should be fast enough but if its not we have to look into another +/// method of checking. +extern "C" bool LLVMRustTargetHasMnemonic(LLVMTargetMachineRef TM, + const char *Mnemonic) { + TargetMachine *Target = unwrap(TM); + const MCInstrInfo *MII = Target->getMCInstrInfo(); + StringRef MnemonicRef(Mnemonic); + + for (unsigned i = 0; i < MII->getNumOpcodes(); i++) { + StringRef Name = MII->getName(i); + if (Name.equals_insensitive(MnemonicRef)) { + return true; + } + } + return false; +} + enum class LLVMRustCodeModel { Tiny, Small, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 60237c98fed2c..e1ef06ca7c713 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1416,12 +1416,12 @@ impl<'tcx> TyCtxt<'tcx> { self, stable_crate_id: StableCrateId, ) -> Result, CrateNum> { - if let Some(&existing) = self.untracked().stable_crate_ids.read().get(&stable_crate_id) { + let mut lock = self.untracked().stable_crate_ids.write(); + if let Some(&existing) = lock.get(&stable_crate_id) { return Err(existing); } - - let num = CrateNum::new(self.untracked().stable_crate_ids.read().len()); - self.untracked().stable_crate_ids.write().insert(stable_crate_id, num); + let num = CrateNum::new(lock.len()); + lock.insert(stable_crate_id, num); Ok(TyCtxtFeed { key: num, tcx: self }) } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 857a4056bae87..6199e3766604d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -924,22 +924,24 @@ pub(crate) struct IrrefutableLetPatternsIfLetGuard { } #[derive(Diagnostic)] -#[diag( - "irrefutable `let...else` {$count -> - [one] pattern - *[other] patterns -}" -)] -#[note( - "{$count -> - [one] this pattern always matches, so the else clause is unreachable - *[other] these patterns always match, so the else clause is unreachable -}" -)] +#[diag("unreachable `else` clause")] +#[note("this pattern always matches, so the else clause is unreachable")] pub(crate) struct IrrefutableLetPatternsLetElse { - pub(crate) count: usize, - #[help("remove this `else` block")] - pub(crate) else_span: Option, + #[subdiagnostic] + pub(crate) be_replaced: Option, +} + +#[derive(Subdiagnostic, Debug)] +#[suggestion( + "consider using `let {$lhs} = {$rhs}` to match on a specific variant", + code = "let {lhs} = {rhs}", + applicability = "machine-applicable" +)] +pub(crate) struct LetElseReplacementSuggestion { + #[primary_span] + pub(crate) span: Span, + pub(crate) lhs: String, + pub(crate) rhs: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8a34320990e19..4dc3e02ace71a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -168,7 +168,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return }; // Lint only single irrefutable let binding. if let [Some((_, Irrefutable))] = chain_refutabilities[..] { - self.lint_single_let(ex.span, None); + self.lint_single_let(ex.span, None, None); } return; } @@ -438,7 +438,45 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { if let LetSource::PlainLet = self.let_source { self.check_binding_is_irrefutable(pat, "local binding", scrut, Some(span)); } else if let Ok(Irrefutable) = self.is_let_irrefutable(pat, scrut) { - self.lint_single_let(span, else_span); + if span.from_expansion() { + self.lint_single_let(span, None, None); + return; + } + let let_else_span = self.check_irrefutable_option_some(pat, scrut, span); + + let sm = self.tcx.sess.source_map(); + let next_token_start = sm.span_extend_while_whitespace(span.clone()).hi(); + let line_span = sm.span_extend_to_line(span.clone()).with_lo(next_token_start); + let else_keyword_span = sm.span_until_whitespace(line_span); + self.lint_single_let(span, Some(else_keyword_span), let_else_span); + } + } + + /// Check case `let x = Some(y);`, user likely intended to destructure `Option` + fn check_irrefutable_option_some( + &self, + pat: &'p Pat<'tcx>, + initializer: Option<&Expr<'tcx>>, + span: Span, + ) -> Option { + if let sm = self.tcx.sess.source_map() + && let Some(initializer) = initializer + && let Some(s_ty) = initializer.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, s_ty.did()) + && let ExprKind::Scope { value, .. } = initializer.kind + && let initializer_expr = &self.thir[value] + && let ExprKind::Adt(box AdtExpr { fields, .. }) = &initializer_expr.kind + && let Some(field) = fields.first() + && let inner = &self.thir[field.expr] + && let Some(inner_ty) = inner.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, inner_ty.did()) + && let Ok(rhs) = sm.span_to_snippet(inner.span) + && let Ok(lhs) = sm.span_to_snippet(pat.span) + { + let lhs = format!("Some({})", lhs); + Some(LetElseReplacementSuggestion { span, lhs, rhs }) + } else { + None } } @@ -559,14 +597,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn lint_single_let(&mut self, let_span: Span, else_span: Option) { + fn lint_single_let( + &mut self, + let_span: Span, + else_keyword_span: Option, + let_else_span: Option, + ) { report_irrefutable_let_patterns( self.tcx, self.hir_source, self.let_source, 1, let_span, - else_span, + else_keyword_span, + let_else_span, ); } @@ -862,7 +906,8 @@ fn report_irrefutable_let_patterns( source: LetSource, count: usize, span: Span, - else_span: Option, + else_keyword_span: Option, + let_else_span: Option, ) { macro_rules! emit_diag { ($lint:tt) => {{ @@ -875,11 +920,23 @@ fn report_irrefutable_let_patterns( LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => { + let spans = match else_keyword_span { + Some(else_keyword_span) => { + let mut spans = MultiSpan::from_span(else_keyword_span); + spans.push_span_label( + span, + msg!("assigning to binding pattern will always succeed"), + ); + spans + } + None => span.into(), + }; + tcx.emit_node_span_lint( IRREFUTABLE_LET_PATTERNS, id, - span, - IrrefutableLetPatternsLetElse { count, else_span }, + spans, + IrrefutableLetPatternsLetElse { be_replaced: let_else_span }, ); } LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index cd9d573957f45..63806cbc701e6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1487,11 +1487,7 @@ impl Options { } pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.cg.symbol_mangling_version.unwrap_or(if self.unstable_features.is_nightly_build() { - SymbolManglingVersion::V0 - } else { - SymbolManglingVersion::Legacy - }) + self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::V0) } #[inline] diff --git a/compiler/rustc_session/src/config/print_request.rs b/compiler/rustc_session/src/config/print_request.rs index b87236cef7646..65e25ab5e6006 100644 --- a/compiler/rustc_session/src/config/print_request.rs +++ b/compiler/rustc_session/src/config/print_request.rs @@ -15,6 +15,7 @@ use crate::macros::AllVariants; pub struct PrintRequest { pub kind: PrintKind, pub out: OutFileName, + pub arg: Option, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -22,6 +23,7 @@ pub struct PrintRequest { pub enum PrintKind { // tidy-alphabetical-start AllTargetSpecsJson, + BackendHasMnemonic, BackendHasZstd, CallingConventions, Cfg, @@ -55,6 +57,7 @@ impl PrintKind { match self { // tidy-alphabetical-start AllTargetSpecsJson => "all-target-specs-json", + BackendHasMnemonic => "backend-has-mnemonic", BackendHasZstd => "backend-has-zstd", CallingConventions => "calling-conventions", Cfg => "cfg", @@ -108,7 +111,8 @@ impl PrintKind { // Unstable values: AllTargetSpecsJson => false, - BackendHasZstd => false, // (perma-unstable, for use by compiletest) + BackendHasMnemonic => false, // (perma-unstable, for use by compiletest) + BackendHasZstd => false, // (perma-unstable, for use by compiletest) CheckCfg => false, CrateRootLintLevels => false, SupportedCrateTypes => false, @@ -145,11 +149,19 @@ pub(crate) fn collect_print_requests( ) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_deref() == Some("help") { - prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetCPUs, + out: OutFileName::Stdout, + arg: None, + }); cg.target_cpu = None; }; if cg.target_feature == "help" { - prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetFeatures, + out: OutFileName::Stdout, + arg: None, + }); cg.target_feature = String::new(); } @@ -162,9 +174,22 @@ pub(crate) fn collect_print_requests( prints.extend(matches.opt_strs("print").into_iter().map(|req| { let (req, out) = split_out_file_name(&req); - let kind = if let Some(print_kind) = PrintKind::from_str(req) { + let (kind, arg) = if let Some(mnemonic) = req.strip_prefix("backend-has-mnemonic") { + check_print_request_stability(early_dcx, unstable_opts, PrintKind::BackendHasMnemonic); + // BackendHasMnemonic requires a mnemonic argument + if let Some(mnemonic) = mnemonic.strip_prefix(':') + && !mnemonic.is_empty() + { + (PrintKind::BackendHasMnemonic, Some(mnemonic.to_string())) + } else { + early_dcx.early_fatal( + "expected mnemonic name after `--print=backend-has-mnemonic:`, \ + for example: `--print=backend-has-mnemonic:RET`", + ); + } + } else if let Some(print_kind) = PrintKind::from_str(req) { check_print_request_stability(early_dcx, unstable_opts, print_kind); - print_kind + (print_kind, None) } else { let is_nightly = nightly_options::match_is_nightly_build(matches); emit_unknown_print_request_help(early_dcx, req, is_nightly) @@ -180,7 +205,7 @@ pub(crate) fn collect_print_requests( } } - PrintRequest { kind, out } + PrintRequest { kind, out, arg } })); prints diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2a2d46615e2e7..a4e9a89a78c7a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2166,7 +2166,7 @@ options! { "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"), + "which mangling version to use for symbol names ('legacy', 'v0' (default), or 'hashed')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index f0587b8e4e23e..0f36edcdd830e 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -554,11 +554,7 @@ fn evaluate_host_effect_for_fn_goal<'tcx>( // but they don't really need to right now. ty::CoroutineClosure(_, _) => return Err(EvaluationFailure::NoSolution), - ty::Closure(def, args) => { - // For now we limit ourselves to closures without binders. The next solver can handle them. - args.as_closure().sig().no_bound_vars().ok_or(EvaluationFailure::NoSolution)?; - (def, args) - } + ty::Closure(def, args) => (def, args), // Everything else needs explicit impls or cannot have an impl _ => return Err(EvaluationFailure::NoSolution), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d4dd33b948193..02cd88a6a4340 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -40,9 +40,6 @@ //! } //! ``` //! -// -// FIXME: Show how `Option` is used in practice, with lots of methods -// //! # Options and pointers ("nullable" pointers) //! //! Rust's pointer types must always point to a valid location; there are diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 3a4e1e657a3da..48bf57356b575 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1794,6 +1794,7 @@ mod prim_ref {} /// have different sizes. /// /// ### ABI compatibility +/// [ABI compatibility]: #abi-compatibility /// /// Generally, when a function is declared with one signature and called via a function pointer with /// a different signature, the two signatures must be *ABI-compatible* or else calling the function @@ -1831,7 +1832,7 @@ mod prim_ref {} /// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box` (specifically, only `Box`), and /// `NonNull` are all ABI-compatible with each other for all `T`. They are also ABI-compatible /// with each other for _different_ `T` if they have the same metadata type (`::Metadata`). +/// Pointee>::Metadata`). However, see the [Control Flow Integrity][cfi-docs] docs for caveats. /// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is /// ABI-compatible with the `iN` integer type of the same size. /// - `char` is ABI-compatible with `u32`. @@ -1890,6 +1891,8 @@ mod prim_ref {} /// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// +/// [cfi-docs]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity +/// /// ### Trait implementations /// /// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index e9659f0176fc5..473c5f3e0faab 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -687,16 +687,6 @@ impl Builder<'_> { rustflags.arg(sysroot_str); } - let use_new_symbol_mangling = self.config.rust_new_symbol_mangling.or_else(|| { - if mode != Mode::Std { - // The compiler and tools default to the new scheme - Some(true) - } else { - // std follows the flag's default, which per compiler-team#938 is v0 on nightly - None - } - }); - // By default, windows-rs depends on a native library that doesn't get copied into the // sysroot. Passing this cfg enables raw-dylib support instead, which makes the native // library unnecessary. This can be removed when windows-rs enables raw-dylib @@ -706,7 +696,8 @@ impl Builder<'_> { rustflags.arg("--cfg=windows_raw_dylib"); } - if let Some(usm) = use_new_symbol_mangling { + // When unset, follow the default of the compiler flag - the compiler, tools and std use v0 + if let Some(usm) = self.config.rust_new_symbol_mangling { rustflags.arg(if usm { "-Csymbol-mangling-version=v0" } else { diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 4c534e9ae0eda..53a6c0cb5737d 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -346,6 +346,17 @@ See also the [codegen tests](#codegen-tests) for a similar set of tests. If you need to work with `#![no_std]` cross-compiling tests, consult the [`minicore` test auxiliary](./minicore.md) chapter. +#### Conditional assembly tests based on instruction support + +Tests that depend on specific assembly instructions being available can use the +`//@ needs-asm-mnemonic: ` directive. This will skip the test if the +target backend does not support the specified instruction mnemonic. + +For example, a test that requires the `RET` instruction: +```rust,ignore +//@ needs-asm-mnemonic: RET +``` + [`tests/assembly-llvm`]: https://github.com/rust-lang/rust/tree/HEAD/tests/assembly-llvm diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 38450d991d05a..caa400b573135 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -163,6 +163,9 @@ The following directives will check rustc build settings and target settings: For tests that cross-compile to explicit targets via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. +- `needs-asm-mnemonic: ` — ignores if the target backend does not + support the specified assembly mnemonic (e.g., `RET`, `NOP`). + Only supported with the LLVM backend. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not enabled for the target (`build.profiler = true` in `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled diff --git a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md index 001159b0d3266..c87cc1d5f863d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md +++ b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md @@ -15,7 +15,7 @@ From the wider Wasm ecosystem perspective, implementing WALI within engines allo ## Requirements ### Compilation -This target is cross-compiled and requires an installation of the [WALI compiler/sysroot](https://github.com/arjunr2/WALI). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). +This target is cross-compiled and requires an installation of the [WALI sysroot](https://github.com/Wasm-Thin-Kernel-Interfaces/WALI.git). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). `wali` targets *minimally require* the following LLVM feature flags: @@ -31,7 +31,7 @@ This target is cross-compiled and requires an installation of the [WALI compiler > **Note**: Users can expect that new enabled-by-default Wasm features for LLVM are transitively incorporatable into this target -- see [wasm32-unknown-unknown](wasm32-unknown-unknown.md) for detailed information on WebAssembly features. -> **Note**: The WALI ABI is similar to default Clang wasm32 ABIs but *not identical*. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maintain minimum source code changes for 64-bit host platforms currently supported. This may change in the future as the spec evolves. +> **Note**: The WALI ABI is *not identical* to the `wasm32-wasip2` or `wasm32-unknown-unknown` ABI. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maximize portability with minimum source code changes for currently supported 64-bit host platforms. These ABIs may converge in the future as the spec evolves. ### Execution Running generated WALI binaries also requires a supported compliant engine implementation -- a working implementation in the [WebAssembly Micro-Runtime (WAMR)](https://github.com/arjunr2/WALI) is included in the repo. @@ -41,38 +41,28 @@ Running generated WALI binaries also requires a supported compliant engine imple ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `config.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): +list in `bootstrap.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `bootstrap.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): ```toml [build] target = ["wasm32-wali-linux-musl"] [target.wasm32-wali-linux-musl] -musl-root = "/wali-musl/sysroot" -llvm-config = "/llvm-project/build/bin/llvm-config" -cc = "/llvm-project/build/bin/clang-18" -cxx = "/llvm-project/build/bin/clang-18" -ar = "/llvm-project/build/bin/llvm-ar" -ranlib = "/llvm-project/build/bin/llvm-ranlib" +musl-root = "/build/sysroot" +cc = "/build/llvm/bin/clang" +cxx = "/build/llvm/bin/clang++" +ar = "/build/llvm/bin/llvm-ar" +ranlib = "/build/llvm/bin/llvm-ranlib" llvm-libunwind = "system" crt-static = true ``` -> The `llvm-config` settings are only temporary, and the changes will eventually be upstreamed into LLVM - ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using -`build-std` or similar. - -Rust program builds can use this target normally. Currently, linking WALI programs may require pointing the `linker` to the llvm build in the [Cargo config](https://doc.rust-lang.org/cargo/reference/config.html) (until LLVM is upstreamed). A `config.toml` for Cargo will look like the following: - -```toml -[target.wasm32-wali-linux-musl] -linker = "/llvm-project/build/bin/lld" -``` +`build-std` or similar (with the appropriate sysroot links). Note that the following `cfg` directives are set for `wasm32-wali-linux-*`: diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md index ad565da9746cb..3f7d55063ca6a 100644 --- a/src/doc/rustc/src/symbol-mangling/index.md +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -46,7 +46,6 @@ foo::example_function ## Mangling versions -`rustc` supports different mangling versions which encode the names in different ways. -The legacy version (which is currently the default on beta/stable) is not described here. -The "v0" mangling scheme addresses several limitations of the legacy format, -and is described in the [v0 Symbol Format](v0.md) chapter. +There is currently one stable mangling scheme version - `v0`. On nightly builds, rustc supports +switching back to the `legacy` mangling scheme using [`-C symbol-mangling-version`]. The `v0` +mangling scheme is described in the [v0 Symbol Format](v0.md) chapter. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index b0f6c97ff5a73..5bd518b14154b 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -246,6 +246,37 @@ Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI. See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. +## Divergence from the Rust ABI + +There are some caveats to [the ABI-compatibility rules for Rust-to-Rust +calls][rust-abi] due to how the CFI sanitizer is implemented. CFI is a tool +that can be used to validate that dynamic function calls respect the ABI, but +due to its C/C++ origins, it disagrees with the above documented guarantees in +a few ways, see below. As CFI is unstable, the details may change in the +future. + +When running the CFI sanitizer, pointer types are only ABI-compatible if the +target type and mutability is the same. This means that `*mut String` and `*mut +i32` are incompatible when using CFI. It also means that `*mut i32` is +incompatible with `*const i32`. The `NonNull<_>` and `Box<_>` pointer types are +currently considered immutable under CFI. For non-primitive target types, CFI +uses the name of the type for its compatibility check. + +When not using the `-Zsanitizer-cfi-normalize-integers` flag, the CFI sanitizer +further restricts the rules by considering `usize`/`isize` incompatible with +the `uN`/`iN` integer type of the same size. + +Unlike other cases where the function ABI is violated, function calls that +violate the CFI-specific ABI-compatibility rules are not undefined behavior. +They are guaranteed to either function correctly, or to crash the program. + +This section only covers cases where CFI disagrees with the ABI-compatibility +rules for Rust-to-Rust calls. It is not meant to be a complete explanation of +how CFI works, and details important for C-to-Rust or Rust-to-C calls are +omitted. + +[rust-abi]: https://doc.rust-lang.org/stable/std/primitive.fn.html#abi-compatibility + ## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination ```rust diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 0d06f6e75af7c..5ef0335b24e58 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -156,6 +156,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "minicore-compile-flags", + "needs-asm-mnemonic", "needs-asm-support", "needs-backends", "needs-crate-type", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index e9f3d6c28d6ef..88ca347edd0a5 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -290,6 +290,37 @@ pub(super) fn handle_needs( } } + if name == "needs-asm-mnemonic" { + let Some(rest) = ln.value_after_colon() else { + return IgnoreDecision::Error { + message: "expected `needs-asm-mnemonic` to have a mnemonic name after colon" + .to_string(), + }; + }; + + if !config.default_codegen_backend.is_llvm() { + return IgnoreDecision::Ignore { + reason: "skipping test as non-LLVM backend does not support mnemonic queries" + .to_string(), + }; + } + + let mnemonic = rest.trim(); + let has_mnemonic = match mnemonic { + "ret" => cache.has_ret_mnemonic, + "nop" => cache.has_nop_mnemonic, + _ => has_mnemonic(config, mnemonic), + }; + + if has_mnemonic { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!("skipping test as target does not have `{mnemonic}` mnemonic"), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -352,6 +383,10 @@ pub(super) struct CachedNeedsConditions { symlinks: bool, /// Whether LLVM built with zstd, for the `needs-llvm-zstd` directive. llvm_zstd: bool, + /// Might add particular other mnemonics heavily needed by tests here. + /// Otherwise call into llvm for every check + has_ret_mnemonic: bool, + has_nop_mnemonic: bool, } impl CachedNeedsConditions { @@ -399,6 +434,8 @@ impl CachedNeedsConditions { llvm_zstd: llvm_has_zstd(&config), dlltool: find_dlltool(&config), symlinks: has_symlinks(), + has_ret_mnemonic: has_mnemonic(config, "ret"), + has_nop_mnemonic: has_mnemonic(config, "nop"), } } } @@ -466,3 +503,26 @@ fn llvm_has_zstd(config: &Config) -> bool { _ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"), } } + +fn has_mnemonic(config: &Config, mnemonic: &str) -> bool { + if !config.default_codegen_backend.is_llvm() { + return false; + } + + let target_flag = format!("--target={}", config.target); + let output = query_rustc_output( + config, + &[ + &target_flag, + "-Zunstable-options", + &format!("--print=backend-has-mnemonic:{}", mnemonic), + ], + Default::default(), + ); + + match output.trim() { + "true" => true, + "false" => false, + _ => panic!("unexpected output from `--print=backend-has-mnemonic:{mnemonic}`: {output:?}"), + } +} diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 4cd75fcfa511a..56d52982a8211 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -1254,3 +1254,25 @@ fn test_edition_range_edition_to_test() { assert_edition_to_test(2018, range, Some(e2024)); assert_edition_to_test(2018, range, Some(efuture)); } + +#[test] +fn needs_asm_mnemonic() { + let config_x86_64 = cfg().target("x86_64-unknown-linux-gnu").build(); + let config_aarch64 = cfg().target("aarch64-unknown-linux-gnu").build(); + + // invalid mnemonic + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:GRUGGY")); + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:gruggy")); + + // valid x86 and aarch64 + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:RET")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:ret")); + + // this is aarch64 specific + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:ldrsbwui")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:LDRSBWui")); + + // this is x86 specific + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:CMPxCHG16B")); + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:CMPXchg16B")); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 568e307366641..ab268f944816f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -319,20 +319,6 @@ impl<'test> TestCx<'test> { TestMode::RustdocJs => true, TestMode::Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build), TestMode::Crashes => false, - TestMode::Incremental => { - let revision = - self.revision.expect("incremental tests require a list of revisions"); - if revision.starts_with("cpass") - || revision.starts_with("bpass") - || revision.starts_with("rpass") - { - true - } else if revision.starts_with("bfail") { - false - } else { - panic!("revision name must begin with `cpass`, `bfail`, `bpass`, or `rpass`"); - } - } mode => panic!("unimplemented for mode {:?}", mode), } } diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 85e0c89a8d018..6529882715a90 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,26 +1,43 @@ -use super::{Emit, FailMode, PassMode, ProcRes, TestCx, WillExecute}; +use std::sync::LazyLock; + +use crate::runtest::{Emit, TestCx, WillExecute}; +use crate::util::string_enum; + +string_enum!( + /// How far an incremental test revision should proceed through the compile/run + /// sequence, and whether the last step should succeed or fail, as determined + /// from the start of the revision name. + #[derive(Clone, Copy, PartialEq, Eq)] + enum IncrRevKind { + CheckPass => "cpass", + BuildFail => "bfail", + BuildPass => "bpass", + RunPass => "rpass", + } +); + +impl IncrRevKind { + fn for_revision_name(rev_name: &str) -> Result { + static MESSAGE: LazyLock = LazyLock::new(|| { + let values = IncrRevKind::STR_VARIANTS + .iter() + .map(|s| format!("`{s}`")) + .collect::>() + .join(", "); + format!("incremental revision name must begin with one of: {values}") + }); + + IncrRevKind::VARIANTS + .iter() + .copied() + .find(|kind| rev_name.starts_with(kind.to_str())) + .ok_or_else(|| MESSAGE.as_str()) + } +} impl TestCx<'_> { + /// Runs a single revision of an incremental test. pub(super) fn run_incremental_test(&self) { - // Basic plan for a test incremental/foo/bar.rs: - // - load list of revisions rpass1, bfail2, rpass3 - // - each should begin with `bfail`, `bpass`, or `rpass` - // - if `bfail`, expect compilation to fail - // - if `bpass`, expect compilation to succeed, don't execute - // - if `rpass`, expect compilation and execution to succeed - // - create a directory build/foo/bar.incremental - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 - // - because name of revision starts with "rpass", expect success - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C bfail2 - // - because name of revision starts with "bfail", expect an error - // - load expected errors as usual, but filter for those with `[bfail2]` - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3 - // - because name of revision starts with "rpass", expect success - // - execute build/foo/bar.exe and save output - // - // FIXME -- use non-incremental mode as an oracle? That doesn't apply - // to #[rustc_clean] tests I guess - let revision = self.revision.expect("incremental tests require a list of revisions"); // Incremental workproduct directory should have already been created. @@ -31,68 +48,63 @@ impl TestCx<'_> { write!(self.stdout, "revision={:?} props={:#?}", revision, self.props); } - if revision.starts_with("cpass") { - self.run_cpass_test(); - } else if revision.starts_with("bpass") { - self.run_bpass_test(); - } else if revision.starts_with("rpass") { - self.run_rpass_test(); - } else if revision.starts_with("bfail") { - self.run_bfail_test(); - } else { - self.fatal("revision name must begin with `bfail`, `bpass`, or `rpass`"); + // Determine the revision kind from the revision name. + // The revision kind should be matched exhaustively to ensure that no cases are missed. + let rev_kind = IncrRevKind::for_revision_name(revision).unwrap_or_else(|e| self.fatal(e)); + + // Compile the test for this revision. + let emit = match rev_kind { + IncrRevKind::CheckPass => Emit::Metadata, // Do a check build. + IncrRevKind::BuildFail | IncrRevKind::BuildPass | IncrRevKind::RunPass => Emit::None, + }; + let will_execute = match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => { + WillExecute::No + } + IncrRevKind::RunPass => { + // Yes, unless running test binaries is disabled. + self.run_if_enabled() + } + }; + let proc_res = &self.compile_test(will_execute, emit); + + // Check the compiler's exit status. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildPass | IncrRevKind::RunPass => { + // Compilation should have succeeded. + if !proc_res.status.success() { + self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); + } + } + + IncrRevKind::BuildFail => { + // Compilation should have failed, with the expected status code. + if proc_res.status.success() { + self.fatal_proc_rec("incremental test did not emit an error", proc_res); + } + if !self.props.dont_check_failure_status { + self.check_correct_failure_status(proc_res); + } + } } - } - - fn run_cpass_test(&self) { - let proc_res = self.compile_test(WillExecute::No, Emit::Metadata); - self.check_if_test_should_compile(None, Some(PassMode::Check), &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_bpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let proc_res = self.compile_test(WillExecute::No, emit_metadata); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_rpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, emit_metadata); - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - - if let WillExecute::Disabled = should_run { - return; - } - - let proc_res = self.exec_compiled_test(); - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } - - fn run_bfail_test(&self) { - let pm = self.pass_mode(); - let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); - self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn check_compiler_output_for_incr(&self, proc_res: &ProcRes) { + // Check compilation output. let output_to_check = self.get_output(proc_res); self.check_expected_errors(&proc_res); self.check_all_error_patterns(&output_to_check, proc_res); self.check_forbid_output(&output_to_check, proc_res); + + // Run the binary and check its exit status, if appropriate. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => {} + IncrRevKind::RunPass => { + if self.config.run_enabled() { + let run_proc_res = self.exec_compiled_test(); + if !run_proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &run_proc_res); + } + } + } + } } } diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index 80e6ac7bb0f03..87be219a2b2e0 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -297,7 +297,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } -// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 0, 3\))?}} %x.0, i16 %x.1) +// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 -1, 2\))?}} %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { x diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs index 1be22de367c99..8e4c26fc34508 100644 --- a/tests/run-make/naked-dead-code-elimination/rmake.rs +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -1,5 +1,6 @@ //@ ignore-cross-compile //@ needs-asm-support +//@ needs-asm-mnemonic: RET use run_make_support::symbols::object_contains_any_symbol; use run_make_support::{bin_name, rustc}; diff --git a/tests/run-make/print-request-help-stable-unstable/help-diff.diff b/tests/run-make/print-request-help-stable-unstable/help-diff.diff index e382a24782711..828a98d96b563 100644 --- a/tests/run-make/print-request-help-stable-unstable/help-diff.diff +++ b/tests/run-make/print-request-help-stable-unstable/help-diff.diff @@ -2,6 +2,6 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models` -+ = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` ++ = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err index 70764ea13aa87..d0e4c81f1de9d 100644 --- a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err +++ b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err @@ -1,5 +1,5 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/raw-dylib-whitespace/main.rs b/tests/run-make/raw-dylib-whitespace/main.rs new file mode 100644 index 0000000000000..023c3570c3262 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/main.rs @@ -0,0 +1,18 @@ +type BOOL = i32; + +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} + +fn main() { + let mut num: u8 = 0; + unsafe { + ProcessPrng(&mut num, 1); + } + println!("{num}"); +} diff --git a/tests/run-make/raw-dylib-whitespace/rmake.rs b/tests/run-make/raw-dylib-whitespace/rmake.rs new file mode 100644 index 0000000000000..45a557aa37387 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/rmake.rs @@ -0,0 +1,15 @@ +// Ensure that raw-dylib still works if the output directory contains spaces. + +//@ only-windows-gnu +//@ ignore-cross-compile + +use run_make_support::{rfs, rustc}; + +fn main() { + let out_dir = "path with spaces"; + rfs::create_dir_all(out_dir); + unsafe { + std::env::set_var("TMP", out_dir); + } + rustc().crate_type("bin").input("main.rs").out_dir(out_dir).run(); +} diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index 0acbb766c1556..1531f61089e9a 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 4075dd0282999..f96feccf35980 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/ui/compile-flags/invalid/print-without-arg.stderr b/tests/ui/compile-flags/invalid/print-without-arg.stderr index ff9669614360a..98788b4b87228 100644 --- a/tests/ui/compile-flags/invalid/print-without-arg.stderr +++ b/tests/ui/compile-flags/invalid/print-without-arg.stderr @@ -3,5 +3,5 @@ error: Argument to option 'print' missing --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . diff --git a/tests/ui/compile-flags/invalid/print.stderr b/tests/ui/compile-flags/invalid/print.stderr index e2521ebf26a41..3eb7634d915db 100644 --- a/tests/ui/compile-flags/invalid/print.stderr +++ b/tests/ui/compile-flags/invalid/print.stderr @@ -1,5 +1,5 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/consts/const-closure-hkl.rs b/tests/ui/consts/const-closure-hkl.rs new file mode 100644 index 0000000000000..25927b3a61ecd --- /dev/null +++ b/tests/ui/consts/const-closure-hkl.rs @@ -0,0 +1,20 @@ +//! Regression test for hkl const closures not working in old solver + +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(const_trait_impl)] +#![feature(const_closures)] +const fn partial_compare() { + let len_chain = const move |_a: &_, _b: &_| {}; + + chaining_impl(len_chain); +} + +const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { + std::mem::forget(x); +} + +fn main() {} diff --git a/tests/ui/let-else/let-else-irrefutable-152938.rs b/tests/ui/let-else/let-else-irrefutable-152938.rs index 6e0ffe3fb8706..25e3e0f6e5708 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.rs +++ b/tests/ui/let-else/let-else-irrefutable-152938.rs @@ -6,7 +6,7 @@ pub fn say_hello(name: Option) { let name_str = Some(name) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause drop(name_str); } diff --git a/tests/ui/let-else/let-else-irrefutable-152938.stderr b/tests/ui/let-else/let-else-irrefutable-152938.stderr index 57632964be9b3..e32f4960a3350 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.stderr +++ b/tests/ui/let-else/let-else-irrefutable-152938.stderr @@ -1,16 +1,18 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable-152938.rs:8:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable-152938.rs:8:31 | LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable-152938.rs:8:36 - | -LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default +help: consider using `let Some(name_str) = name` to match on a specific variant + | +LL - let name_str = Some(name) else { return; }; +LL + let Some(name_str) = name else { return; }; + | warning: 1 warning emitted diff --git a/tests/ui/let-else/let-else-irrefutable.rs b/tests/ui/let-else/let-else-irrefutable.rs index f9675ff5938eb..59de726d38ddf 100644 --- a/tests/ui/let-else/let-else-irrefutable.rs +++ b/tests/ui/let-else/let-else-irrefutable.rs @@ -1,10 +1,18 @@ //@ check-pass fn main() { - let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern + let x = 1 else { return }; //~ WARN unreachable `else` clause // Multiline else blocks should not get printed - let x = 1 else { //~ WARN irrefutable `let...else` pattern + let x = 1 else { //~ WARN unreachable `else` clause + eprintln!("problem case encountered"); + return + }; + + let case = Some("a"); + let name = Some(case) else { + //~^ WARN unreachable `else` clause + //~| HELP consider using `let Some(name) = case` to match on a specific variant eprintln!("problem case encountered"); return }; diff --git a/tests/ui/let-else/let-else-irrefutable.stderr b/tests/ui/let-else/let-else-irrefutable.stderr index d36d227b4156a..12338789d2a03 100644 --- a/tests/ui/let-else/let-else-irrefutable.stderr +++ b/tests/ui/let-else/let-else-irrefutable.stderr @@ -1,33 +1,38 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:4:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:4:15 | LL | let x = 1 else { return }; - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:4:20 - | -LL | let x = 1 else { return }; - | ^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:7:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:7:15 | LL | let x = 1 else { - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed + | + = note: this pattern always matches, so the else clause is unreachable + +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:13:27 + | +LL | let name = Some(case) else { + | --------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:7:20 - | -LL | let x = 1 else { - | ____________________^ -LL | | eprintln!("problem case encountered"); -LL | | return -LL | | }; - | |_____^ +help: consider using `let Some(name) = case` to match on a specific variant + | +LL - let name = Some(case) else { +LL + let Some(name) = case else { + | -warning: 2 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 3ede26dbcd06c..a552fbcfc1fc3 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -93,10 +93,10 @@ fn i() { fn j() { let mut bar = 0; let foo = bar = { - //~^ WARN irrefutable `let...else` pattern 1 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } @@ -158,21 +158,21 @@ fn o() -> Result<(), ()> { fn q() { let foo = |x: i32| { - //~^ WARN irrefutable `let...else` pattern x } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn r() { let ok = format_args!("") else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed - //~| WARN irrefutable `let...else` pattern + //~| WARN unreachable `else` clause } fn s() { @@ -202,10 +202,10 @@ fn t() { } let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { - //~^ WARN irrefutable `let...else` pattern 8 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 8545d95f507f6..76fbbbb8c1e10 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -125,7 +125,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:98:5 + --> $DIR/bad-let-else-statement.rs:97:5 | LL | } else { | ^ @@ -133,7 +133,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ -LL | LL | 1 LL ~ }) else { | @@ -204,7 +203,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:163:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -212,7 +211,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ -LL | LL | x LL ~ }) else { | @@ -230,7 +228,7 @@ LL + let bad = format_args! ("") else { return; }; | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:207:5 + --> $DIR/bad-let-else-statement.rs:206:5 | LL | } else { | ^ @@ -238,7 +236,6 @@ LL | } else { help: use parentheses instead of braces for this macro | LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! ( -LL | LL | 8 LL ~ ) else { | @@ -259,92 +256,62 @@ LL - let 0 = a! {} else { return; }; LL + let 0 = a! () else { return; }; | -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:95:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:97:7 | LL | / let foo = bar = { -LL | | LL | | 1 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:98:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:160:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:162:7 | LL | / let foo = |x: i32| { -LL | | LL | | x LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:163:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:170:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:170:31 | LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:170:36 - | -LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:173:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:173:33 | LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:173:38 - | -LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:204:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:206:7 | LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { -LL | | LL | | 8 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:207:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ error: aborting due to 19 previous errors; 5 warnings emitted diff --git a/tests/ui/print-request/print-lints-help.stderr b/tests/ui/print-request/print-lints-help.stderr index d39c6326e318b..c6e74e7dce7b6 100644 --- a/tests/ui/print-request/print-lints-help.stderr +++ b/tests/ui/print-request/print-lints-help.stderr @@ -1,6 +1,6 @@ error: unknown print request: `lints` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: use `-Whelp` to print a list of lints = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/span/let-offset-of.rs b/tests/ui/span/let-offset-of.rs index 99b34a1928470..eeecf38e6b6a9 100644 --- a/tests/ui/span/let-offset-of.rs +++ b/tests/ui/span/let-offset-of.rs @@ -15,5 +15,5 @@ fn init_to_offset_of() { //~^ WARN irrefutable `if let` pattern let x = offset_of!(Foo, field) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause } diff --git a/tests/ui/span/let-offset-of.stderr b/tests/ui/span/let-offset-of.stderr index df9b1e695b1e4..afcf8a8103d9d 100644 --- a/tests/ui/span/let-offset-of.stderr +++ b/tests/ui/span/let-offset-of.stderr @@ -8,18 +8,15 @@ LL | if let x = offset_of!(Foo, field) {} = help: consider replacing the `if let` with a `let` = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-offset-of.rs:17:5 +warning: unreachable `else` clause + --> $DIR/let-offset-of.rs:17:36 | LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------ ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-offset-of.rs:17:41 - | -LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^ warning: 2 warnings emitted diff --git a/triagebot.toml b/triagebot.toml index 9c69061c7b8cf..33ef3d097e618 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -940,10 +940,6 @@ Issue #{number} "{title}" has been added. # Mentions # ------------------------------------------------------------------------------ -[mentions."triagebot.toml"] -message = "`triagebot.toml` has been modified, there may have been changes to the review queue." -cc = ["@davidtwco", "@wesleywiser"] - [mentions."compiler/rustc_codegen_cranelift"] message = "The Cranelift subtree was changed" cc = ["@bjorn3"]