From a20daf79c016ef12d3b7687a34086754c8b9b7c2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 29 Sep 2025 15:17:11 +0200 Subject: [PATCH 01/12] arm-linux.md: various fixes/improvements --- .../rustc/src/platform-support/arm-linux.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-linux.md b/src/doc/rustc/src/platform-support/arm-linux.md index 5f40743f3d070..b620763fa6df8 100644 --- a/src/doc/rustc/src/platform-support/arm-linux.md +++ b/src/doc/rustc/src/platform-support/arm-linux.md @@ -1,7 +1,7 @@ # Arm Linux support in Rust The Arm Architecture has been around since the mid-1980s, going through nine -major revisions, many minor revisions, and spanning both 32-bith and 64-bit +major revisions, many minor revisions, and spanning both 32-bit and 64-bit architectures. This page covers 32-bit Arm platforms that run some form of Linux (but not Android). Those targets are: @@ -49,7 +49,7 @@ The architecture component simply called `arm` corresponds to the Armv6 architecture - that is, version 6 of the Arm Architecture as defined in version 6 of the Arm Architecture Reference Manual (the Arm ARM). This was the last 'legacy' release of the Arm architecture, before they split into -Application, Real-Time and Microcontroller profiles (leading to Armv7-A, +Application, Real-Time, and Microcontroller profiles (leading to Armv7-A, Armv7-R and Armv7-M). Processors that implement the Armv6 architecture include the ARM1176JZF-S, as found in BCM2835 SoC that powers the Raspberry Pi Zero. Arm processors are generally fairly backwards compatible, especially for @@ -59,7 +59,7 @@ on newer ARMv7-A systems, or even 64/32-bit Armv8-A systems. The `armeb` architecture component specifies an Armv6 processor running in Big Endian mode (`eb` is for big-endian - the letters are backwards because engineers used to little-endian systems perceive big-endian numbers to be -written into memory backwards, and they thought it was funnier like that). +written into memory backwards, and they thought it was funny like that). Most Arm processors can operate in either little-endian or big-endian mode and little-endian mode is by far the most common. However, if for whatever reason you wish to store your Most Significant Bytes first, these targets are @@ -70,7 +70,7 @@ Targets that start with `armv4t` are for processors implementing the Armv4T architecture from 1994. These include the ARM7TDMI, as found in the Nokia 6110 brick-phone and the Game Boy Advance. The 'T' stands for *Thumb* and indicate that the processors can execute smaller 16-bit versions of some of the 32-bit -Arm instructions. Because a Thumb is like a small version of an Arm. +Arm instructions. A Thumb is like a small version of an Arm. Targets that start with `armv5te` are for processors implementing the Armv5TE architecture. These are mostly from the ARM9 family, like the ARM946E-S found @@ -111,11 +111,11 @@ The `gnueabi` ABI component indicates support for using the GNU C Library (glibc), and the Arm Embedded ABI (EABI). The EABI is a replacement for the original ABI (now called the Old ABI or OABI), and it is the standard ABI for 32-bit Arm systems. With this ABI, function parameters that are `f32` or `f64` -are passed as if they were integers, instead of being passed via in FPU -registers. Generally these targets also disable the use of the FPU entirely, +are passed as if they were integers, instead of being passed in FPU +registers. Generally, these targets also disable the use of the FPU entirely, although that isn't always true. -The `gnueabihf` ABI component is like `gnueabi`, except that it support the +The `gnueabihf` ABI component is like `gnueabi`, except that it supports the 'hard-float' of the EABI. That is, function parameters that are `f32` or `f64` are passed in FPU registers. Naturally, this makes the FPU mandatory. @@ -147,7 +147,7 @@ the Arm architecture, and more importantly, knows where to find a suitable C Library to link against. To do that, you can add the `linker` property to your `.cargo/config.toml`. -Typically you would refer to a suitable copy of GCC that has built as a +Typically, you would refer to a suitable copy of GCC that was built as a cross-compiler, alongside a C library. ```toml @@ -155,7 +155,7 @@ cross-compiler, alongside a C library. linker = "arm-linux-gnueabi-gcc" ``` -On Debian Linux, you could install such a cross-compilation toolchain with +On Debian, you could install such a cross-compilation toolchain with `apt install gcc-arm-linux-gnueabi`. For more exotic combinations, you might need to build a bespoke version of GCC using [crosstool-ng]. From 9aeab7807602c24685314e8c0f4e0a33e5ad5818 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Oct 2025 20:57:18 +0200 Subject: [PATCH 02/12] improve text --- src/doc/rustc/src/platform-support/arm-linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/arm-linux.md b/src/doc/rustc/src/platform-support/arm-linux.md index b620763fa6df8..652661b2d3aaf 100644 --- a/src/doc/rustc/src/platform-support/arm-linux.md +++ b/src/doc/rustc/src/platform-support/arm-linux.md @@ -70,7 +70,7 @@ Targets that start with `armv4t` are for processors implementing the Armv4T architecture from 1994. These include the ARM7TDMI, as found in the Nokia 6110 brick-phone and the Game Boy Advance. The 'T' stands for *Thumb* and indicate that the processors can execute smaller 16-bit versions of some of the 32-bit -Arm instructions. A Thumb is like a small version of an Arm. +Arm instructions. This is because a Thumb is like a small version of an Arm. Targets that start with `armv5te` are for processors implementing the Armv5TE architecture. These are mostly from the ARM9 family, like the ARM946E-S found From 124bfc99c3087066c84731e06effcbb6b3a16559 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 13 Oct 2025 11:47:53 -0400 Subject: [PATCH 03/12] Remove parent def lookup hack that is no longer needed The tcx.parent tree appears to be correct now. --- .../rustc_hir_analysis/src/collect/generics_of.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 333cea23c4148..3d2f0466cad08 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -77,20 +77,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // stable enough and does not need a feature gate anymore. Node::AnonConst(_) => { let parent_did = tcx.parent(def_id.to_def_id()); - - // We don't do this unconditionally because the `DefId` parent of an anon const - // might be an implicitly created closure during `async fn` desugaring. This would - // have the wrong generics. - // - // i.e. `async fn foo<'a>() { let a = [(); { 1 + 2 }]; bar().await() }` - // would implicitly have a closure in its body that would be the parent of - // the `{ 1 + 2 }` anon const. This closure's generics is simply a witness - // instead of `['a]`. - let parent_did = if let DefKind::AnonConst = tcx.def_kind(parent_did) { - parent_did - } else { - tcx.hir_get_parent_item(hir_id).to_def_id() - }; debug!(?parent_did); let mut in_param_ty = false; From 379a05702326e64481f828eedd82239fdce1b065 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 13 Oct 2025 11:49:19 -0400 Subject: [PATCH 04/12] Fix lowering of CStr constants to valtrees They need an extra branch for the newtype. --- compiler/rustc_mir_build/src/thir/constant.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 52e6f2d3e1a59..6e071fb344c44 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -58,8 +58,12 @@ pub(crate) fn lit_to_const<'tcx>( (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ty::ValTree::from_scalar_int(tcx, n.into()) } - (ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => { - ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()) + (ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => + { + // A CStr is a newtype around a byte slice, so we create the inner slice here. + // We need a branch for each "level" of the data structure. + let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()); + ty::ValTree::from_branches(tcx, [bytes]) } (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { let scalar_int = trunc(n.get(), *ui); From cff6452e9019051390c9bffc6a80574da71cca9b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 17 Oct 2025 13:32:11 +0200 Subject: [PATCH 05/12] Ignore test-dashboard related files After bors merges a PR, a message may be posted from the CI onto the PR comment thread directing the user to use the following commands to look at the test differences: ``` cargo run --manifest-path src/ci/citool/Cargo.toml -- \ test-dashboard [SOMEID] --output-dir test-dashboard open test-dashboard/index.html ``` This command creates the `.citool-cache` and `test-dashboard` directories, whose contents should not enter the repository and can be ignored by `git`. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 5988a64916ad8..0030f22363c24 100644 --- a/.gitignore +++ b/.gitignore @@ -90,6 +90,10 @@ node_modules ## Rustdoc GUI tests tests/rustdoc-gui/src/**.lock +## Test dashboard +.citool-cache/ +test-dashboard/ + ## direnv /.envrc /.direnv/ From 827bd00438b70bee52f76e72a0da9a42c17bae59 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Tue, 21 Oct 2025 23:11:46 +0300 Subject: [PATCH 06/12] Implement `strip_circumfix` lib feature --- library/core/src/slice/mod.rs | 32 +++++++++++++++++++++++++++++++ library/core/src/str/mod.rs | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 61eb78294f68b..157d7a070d86a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2725,6 +2725,38 @@ impl [T] { None } + /// Returns a subslice with the prefix and suffix removed. + /// + /// If the slice starts with `prefix` and ends with `suffix`, returns the subslice after the + /// prefix and before the suffix, wrapped in `Some`. + /// + /// If the slice does not start with `prefix` or does not end with `suffix`, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(strip_circumfix)] + /// + /// let v = &[10, 50, 40, 30]; + /// assert_eq!(v.strip_circumfix(&[10], &[30]), Some(&[50, 40][..])); + /// assert_eq!(v.strip_circumfix(&[10], &[40, 30]), Some(&[50][..])); + /// assert_eq!(v.strip_circumfix(&[10, 50], &[40, 30]), Some(&[][..])); + /// assert_eq!(v.strip_circumfix(&[50], &[30]), None); + /// assert_eq!(v.strip_circumfix(&[10], &[40]), None); + /// assert_eq!(v.strip_circumfix(&[], &[40, 30]), Some(&[10, 50][..])); + /// assert_eq!(v.strip_circumfix(&[10, 50], &[]), Some(&[40, 30][..])); + /// ``` + #[must_use = "returns the subslice without modifying the original"] + #[unstable(feature = "strip_circumfix", issue = "147946")] + pub fn strip_circumfix(&self, prefix: &P, suffix: &S) -> Option<&[T]> + where + T: PartialEq, + S: SlicePattern + ?Sized, + P: SlicePattern + ?Sized, + { + self.strip_prefix(prefix)?.strip_suffix(suffix) + } + /// Returns a subslice with the optional prefix removed. /// /// If the slice starts with `prefix`, returns the subslice after the prefix. If `prefix` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 82019b9b3afe5..37dc401ed0098 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2447,6 +2447,42 @@ impl str { suffix.strip_suffix_of(self) } + /// Returns a string slice with the prefix and suffix removed. + /// + /// If the string starts with the pattern `prefix` and ends with the pattern `suffix`, returns + /// the substring after the prefix and before the suffix, wrapped in `Some`. + /// Unlike [`trim_start_matches`] and [`trim_end_matches`], this method removes both the prefix + /// and suffix exactly once. + /// + /// If the string does not start with `prefix` or does not end with `suffix`, returns `None`. + /// + /// Each [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a + /// function or closure that determines if a character matches. + /// + /// [`char`]: prim@char + /// [pattern]: self::pattern + /// [`trim_start_matches`]: Self::trim_start_matches + /// [`trim_end_matches`]: Self::trim_end_matches + /// + /// # Examples + /// + /// ``` + /// #![feature(strip_circumfix)] + /// + /// assert_eq!("bar:hello:foo".strip_circumfix("bar:", ":foo"), Some("hello")); + /// assert_eq!("bar:foo".strip_circumfix("foo", "foo"), None); + /// assert_eq!("foo:bar;".strip_circumfix("foo:", ';'), Some("bar")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[unstable(feature = "strip_circumfix", issue = "147946")] + pub fn strip_circumfix(&self, prefix: P, suffix: S) -> Option<&str> + where + for<'a> S::Searcher<'a>: ReverseSearcher<'a>, + { + self.strip_prefix(prefix)?.strip_suffix(suffix) + } + /// Returns a string slice with the optional prefix removed. /// /// If the string starts with the pattern `prefix`, returns the substring after the prefix. From 0efeec580a9cfa426e965af35747cef74d19191c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Sep 2025 23:04:50 +0000 Subject: [PATCH 07/12] Mention crate being analysized in query description "running analysis passes on this crate" -> "running analysis passes on crate `foo`" This message is displayed in cycle errors in particular, and in some cases without any spans or any other identifiable information to determine which dependency introduced the cycle. --- compiler/rustc_middle/src/query/mod.rs | 5 ++++- .../issue-24949-assoc-const-static-recursion-trait.stderr | 2 +- tests/ui/consts/const-eval/const-eval-query-stack.stderr | 2 +- tests/ui/consts/recursive-zst-static.default.stderr | 2 +- tests/ui/consts/recursive-zst-static.unleash.stderr | 2 +- tests/ui/track-diagnostics/track.stderr | 2 +- tests/ui/treat-err-as-bug/err.stderr | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 30d4cc8b3c8d6..db2e252f9406a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -397,7 +397,10 @@ rustc_queries! { /// The root query triggering all analysis passes like typeck or borrowck. query analysis(key: ()) { eval_always - desc { "running analysis passes on this crate" } + desc { |tcx| + "running analysis passes on crate `{}`", + tcx.crate_name(LOCAL_CRATE), + } } /// This query checks the fulfillment of collected lint expectations. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 317af7975aa7e..8197cfcba5025 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -30,7 +30,7 @@ note: ...which requires elaborating drops for ` Date: Fri, 31 Oct 2025 21:22:27 +0000 Subject: [PATCH 08/12] Change cfg_trace, cfg_attr_trace symbol values --- compiler/rustc_span/src/symbol.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c1c9fa57f85b2..e3a4d261ee840 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -625,7 +625,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, - cfg_attr_trace: "", // must not be a valid identifier + cfg_attr_trace: "", // must not be a valid identifier cfg_boolean_literals, cfg_contract_checks, cfg_doctest, @@ -646,7 +646,7 @@ symbols! { cfg_target_has_reliable_f16_f128, cfg_target_thread_local, cfg_target_vendor, - cfg_trace: "", // must not be a valid identifier + cfg_trace: "", // must not be a valid identifier cfg_ub_checks, cfg_version, cfi, From 0bd6a03edf6d0f9957aa85625232c11bf49ee164 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 31 Oct 2025 21:41:12 +0000 Subject: [PATCH 09/12] dangling ptr lint cleanup --- compiler/rustc_lint/messages.ftl | 8 +- .../ui/lint/dangling-pointers-from-locals.rs | 38 ++--- .../lint/dangling-pointers-from-locals.stderr | 152 +++++++++--------- 3 files changed, 99 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1f6a382175b7c..8aa90c070acd3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -193,11 +193,11 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i .current_use = this identifier can be confused with `{$existing_sym}` .other_use = other identifier used here -lint_dangling_pointers_from_locals = a dangling pointer will be produced because the local variable `{$local_var_name}` will be dropped - .ret_ty = return type of the {$fn_kind} is `{$ret_ty}` - .local_var = `{$local_var_name}` is part the {$fn_kind} and will be dropped at the end of the {$fn_kind} +lint_dangling_pointers_from_locals = {$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}` + .ret_ty = return type is `{$ret_ty}` + .local_var = local variable `{$local_var_name}` is dropped at the end of the {$fn_kind} .created_at = dangling pointer created here - .note = pointers do not have a lifetime; after returning, the `{$local_var_ty}` will be deallocated at the end of the {$fn_kind} because nothing is referencing it as far as the type system is concerned + .note = a dangling pointer is safe, but dereferencing one is undefined behavior lint_dangling_pointers_from_temporaries = a dangling pointer will be produced because the temporary `{$ty}` will be dropped .label_ptr = this pointer will immediately be invalid diff --git a/tests/ui/lint/dangling-pointers-from-locals.rs b/tests/ui/lint/dangling-pointers-from-locals.rs index e321df2f42790..a274ab8582b93 100644 --- a/tests/ui/lint/dangling-pointers-from-locals.rs +++ b/tests/ui/lint/dangling-pointers-from-locals.rs @@ -8,46 +8,46 @@ const X: u8 = 5; fn simple() -> *const u8 { let x = 0; &x - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn bindings() -> *const u8 { let x = 0; let x = &x; x - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn bindings_with_return() -> *const u8 { let x = 42; let y = &x; return y; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn with_simple_cast() -> *const u8 { let x = 0u8; &x as *const u8 - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn bindings_and_casts() -> *const u8 { let x = 0u8; let x = &x as *const u8; x as *const u8 - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn return_with_complex_cast() -> *mut u8 { let mut x = 0u8; return &mut x as *mut u8 as *const u8 as *mut u8; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn with_block() -> *const u8 { let x = 0; &{ x } - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn with_many_blocks() -> *const u8 { @@ -55,7 +55,7 @@ fn with_many_blocks() -> *const u8 { { { &{ - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer { x } } } @@ -65,20 +65,20 @@ fn with_many_blocks() -> *const u8 { fn simple_return() -> *const u8 { let x = 0; return &x; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn return_mut() -> *mut u8 { let mut x = 0; return &mut x; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn const_and_flow() -> *const u8 { if false { let x = 8; return &x; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } &X // not dangling } @@ -86,20 +86,20 @@ fn const_and_flow() -> *const u8 { fn vector() -> *const Vec { let x = vec![T::default()]; &x - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn local_adt() -> *const Adt { let x = Adt(5); return &x; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn closure() -> *const u8 { let _x = || -> *const u8 { let x = 8; return &x; - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer }; &X // not dangling } @@ -111,27 +111,27 @@ fn fn_ptr() -> *const fn() -> u8 { let x = ret_u8 as fn() -> u8; &x - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn as_arg(a: Adt) -> *const Adt { &a - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 { &a - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn ptr_as_arg(a: *const Adt) -> *const *const Adt { &a - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn adt_as_arg(a: &Adt) -> *const &Adt { &a - //~^ WARN a dangling pointer will be produced + //~^ WARN dangling pointer } fn unit() -> *const () { diff --git a/tests/ui/lint/dangling-pointers-from-locals.stderr b/tests/ui/lint/dangling-pointers-from-locals.stderr index e1d28bf22a0c1..45acc74ac34e5 100644 --- a/tests/ui/lint/dangling-pointers-from-locals.stderr +++ b/tests/ui/lint/dangling-pointers-from-locals.stderr @@ -1,105 +1,105 @@ -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:10:5 | LL | fn simple() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | &x | ^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior = note: `#[warn(dangling_pointers_from_locals)]` on by default -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:17:5 | LL | fn bindings() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | let x = &x; | -- dangling pointer created here LL | x | ^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:24:12 | LL | fn bindings_with_return() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 42; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | let y = &x; | -- dangling pointer created here LL | return y; | ^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:30:5 | LL | fn with_simple_cast() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0u8; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | &x as *const u8 | --^^^^^^^^^^^^^ | | | dangling pointer created here | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:37:5 | LL | fn bindings_and_casts() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0u8; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | let x = &x as *const u8; | -- dangling pointer created here LL | x as *const u8 | ^^^^^^^^^^^^^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:43:12 | LL | fn return_with_complex_cast() -> *mut u8 { - | ------- return type of the function is `*mut u8` + | ------- return type is `*mut u8` LL | let mut x = 0u8; - | ----- `x` is part the function and will be dropped at the end of the function + | ----- local variable `x` is dropped at the end of the function LL | return &mut x as *mut u8 as *const u8 as *mut u8; | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dangling pointer created here | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:49:5 | LL | fn with_block() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | &{ x } | ^^^^^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:57:13 | LL | fn with_many_blocks() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function ... LL | / &{ LL | | @@ -107,141 +107,141 @@ LL | | { x } LL | | } | |_____________^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:67:12 | LL | fn simple_return() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | let x = 0; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | return &x; | ^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:73:12 | LL | fn return_mut() -> *mut u8 { - | ------- return type of the function is `*mut u8` + | ------- return type is `*mut u8` LL | let mut x = 0; - | ----- `x` is part the function and will be dropped at the end of the function + | ----- local variable `x` is dropped at the end of the function LL | return &mut x; | ^^^^^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:80:16 | LL | fn const_and_flow() -> *const u8 { - | --------- return type of the function is `*const u8` + | --------- return type is `*const u8` LL | if false { LL | let x = 8; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | return &x; | ^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:88:5 | LL | fn vector() -> *const Vec { - | ------------- return type of the function is `*const Vec` + | ------------- return type is `*const Vec` LL | let x = vec![T::default()]; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | &x | ^^ | - = note: pointers do not have a lifetime; after returning, the `Vec` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:94:12 | LL | fn local_adt() -> *const Adt { - | ---------- return type of the function is `*const Adt` + | ---------- return type is `*const Adt` LL | let x = Adt(5); - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | return &x; | ^^ | - = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: closure returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:101:16 | LL | let _x = || -> *const u8 { - | --------- return type of the closure is `*const u8` + | --------- return type is `*const u8` LL | let x = 8; - | - `x` is part the closure and will be dropped at the end of the closure + | - local variable `x` is dropped at the end of the closure LL | return &x; | ^^ | - = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the closure because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `x` will be dropped +warning: function returns a dangling pointer to dropped local variable `x` --> $DIR/dangling-pointers-from-locals.rs:113:5 | LL | fn fn_ptr() -> *const fn() -> u8 { - | ----------------- return type of the function is `*const fn() -> u8` + | ----------------- return type is `*const fn() -> u8` ... LL | let x = ret_u8 as fn() -> u8; - | - `x` is part the function and will be dropped at the end of the function + | - local variable `x` is dropped at the end of the function LL | &x | ^^ | - = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `a` will be dropped +warning: function returns a dangling pointer to dropped local variable `a` --> $DIR/dangling-pointers-from-locals.rs:118:5 | LL | fn as_arg(a: Adt) -> *const Adt { - | - ---------- return type of the function is `*const Adt` + | - ---------- return type is `*const Adt` | | - | `a` is part the function and will be dropped at the end of the function + | local variable `a` is dropped at the end of the function LL | &a | ^^ | - = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `a` will be dropped +warning: function returns a dangling pointer to dropped local variable `a` --> $DIR/dangling-pointers-from-locals.rs:123:5 | LL | fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 { - | - ----------------- return type of the function is `*const fn() -> u8` + | - ----------------- return type is `*const fn() -> u8` | | - | `a` is part the function and will be dropped at the end of the function + | local variable `a` is dropped at the end of the function LL | &a | ^^ | - = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `a` will be dropped +warning: function returns a dangling pointer to dropped local variable `a` --> $DIR/dangling-pointers-from-locals.rs:128:5 | LL | fn ptr_as_arg(a: *const Adt) -> *const *const Adt { - | - ----------------- return type of the function is `*const *const Adt` + | - ----------------- return type is `*const *const Adt` | | - | `a` is part the function and will be dropped at the end of the function + | local variable `a` is dropped at the end of the function LL | &a | ^^ | - = note: pointers do not have a lifetime; after returning, the `*const Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior -warning: a dangling pointer will be produced because the local variable `a` will be dropped +warning: function returns a dangling pointer to dropped local variable `a` --> $DIR/dangling-pointers-from-locals.rs:133:5 | LL | fn adt_as_arg(a: &Adt) -> *const &Adt { - | - ----------- return type of the function is `*const &Adt` + | - ----------- return type is `*const &Adt` | | - | `a` is part the function and will be dropped at the end of the function + | local variable `a` is dropped at the end of the function LL | &a | ^^ | - = note: pointers do not have a lifetime; after returning, the `&Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned + = note: a dangling pointer is safe, but dereferencing one is undefined behavior warning: 19 warnings emitted From f39fb70fb996b7949a0d5f9b3fde1270df689286 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 1 Nov 2025 14:13:33 -0400 Subject: [PATCH 10/12] Update tests after fixing ICEs --- tests/crashes/129209.rs | 11 --------- tests/crashes/131295.rs | 9 ------- tests/crashes/139738.rs | 3 --- .../parent_generics_of_nested_in_default.rs | 6 +++++ ...arent_generics_of_nested_in_default.stderr | 24 +++++++++++++++++++ 5 files changed, 30 insertions(+), 23 deletions(-) delete mode 100644 tests/crashes/129209.rs delete mode 100644 tests/crashes/131295.rs delete mode 100644 tests/crashes/139738.rs create mode 100644 tests/ui/const-generics/parent_generics_of_nested_in_default.rs create mode 100644 tests/ui/const-generics/parent_generics_of_nested_in_default.stderr diff --git a/tests/crashes/129209.rs b/tests/crashes/129209.rs deleted file mode 100644 index 249fa41552ebf..0000000000000 --- a/tests/crashes/129209.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#129209 - -impl< - const N: usize = { - static || { - Foo([0; X]); - } - }, - > PartialEq for True -{ -} diff --git a/tests/crashes/131295.rs b/tests/crashes/131295.rs deleted file mode 100644 index f31d6bc324a26..0000000000000 --- a/tests/crashes/131295.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #131295 - -#![feature(generic_const_exprs)] - -async fn foo<'a>() -> [(); { - let _y: &'a (); - 4 - }] { -} diff --git a/tests/crashes/139738.rs b/tests/crashes/139738.rs deleted file mode 100644 index c0e7307de6c3f..0000000000000 --- a/tests/crashes/139738.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ known-bug: #139738 -#![feature(generic_const_exprs)] -fn b<'a>() -> impl IntoIterator<[(); (|_: &'a u8| 0, 0).1]> {} diff --git a/tests/ui/const-generics/parent_generics_of_nested_in_default.rs b/tests/ui/const-generics/parent_generics_of_nested_in_default.rs new file mode 100644 index 0000000000000..25dc416fc1fd1 --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_nested_in_default.rs @@ -0,0 +1,6 @@ +impl Tr {} +//~^ ERROR cannot find type `Tr` +//~| ERROR cannot find value `B` +//~| ERROR defaults for generic parameters are not allowed here + +fn main() {} diff --git a/tests/ui/const-generics/parent_generics_of_nested_in_default.stderr b/tests/ui/const-generics/parent_generics_of_nested_in_default.stderr new file mode 100644 index 0000000000000..24e05482a1a99 --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_nested_in_default.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `Tr` in this scope + --> $DIR/parent_generics_of_nested_in_default.rs:1:36 + | +LL | impl Tr {} + | ^^ not found in this scope + +error[E0425]: cannot find value `B` in this scope + --> $DIR/parent_generics_of_nested_in_default.rs:1:30 + | +LL | impl Tr {} + | - ^ help: a const parameter with a similar name exists: `A` + | | + | similarly named const parameter `A` defined here + +error: defaults for generic parameters are not allowed here + --> $DIR/parent_generics_of_nested_in_default.rs:1:6 + | +LL | impl Tr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. From 76066d7949257a4b7f73b2b67d6d3a9c5c1a8919 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 2 Nov 2025 15:59:21 +0800 Subject: [PATCH 11/12] test: remove `tests/run-make/fmt-write-bloat/` This test suffers from multiple issues that make it very, very difficult to fix, and even if fixed, it would still be too fragile. For some background context, this test tries to check that the optimization introduced in [PR-78122] is not regressed. The optimization is for eliding `usize` formatting machinery and padding code from the final binary. Previously, writing any `fmt::Arguments` would cause the `usize` formatting and padding machinery to be included in the final binary since indexing used in `fmt::write` generates code using `panic_bounds_check` (that prints the index and length). Those bounds check are never hit, since `fmt::Arguments` never contain any out-of-bounds indicies. The `Makefile` version of `fmt-write-bloat` was ported to the present `rmake.rs` test infra in [PR-128147]. However, this PR just tries to maintain the original test logic. The original test, it turns out, already have multiple limitations: - It only runs on non-Windows, since the `no_std` test of the original version tries to link against a `libc`. [PR-128807] worked around this by using a substitute name. We re-enabled this test in [PR-142841], but it turns out the assertions are too weak, it will even vacuously pass for no symbols at all. - In [PR-143669], we tried to make this test more robust by comparing the set of expected versus unexpected panic-related symbols, subject to if std was built with debug assertions. However, in working on [PR-143669], we've come to realize that this test is fundamentally very fragile: - The set of panic symbols depend on whether the standard library was built with or without debug assertions. - Different platforms often have different sets of panic machinery modules, functions and paths, and thus different sets of panic symbols. For instance, x86_64 msvc and i686 msvc have different panic codepaths. - This comes back to the way the test is trying to gauge the absence of panic symbols -- it tries to look for symbol substring matches for "known" panic symbols. This is fundamentally fragile, because the test is trying to peek into the symbols of the resultant binary post-linking, based on fuzzy matches (the symbols are mangled as well). Based on this assessment, we determined that we should remove this test. This is not intended to exclude the possibility of reintroducing a more robust version of this test. For instance, we could consider some kind of more controllable post-link "end product" integration codegen test suite. [PR-78122]: https://github.com/rust-lang/rust/pull/78122 [PR-128147]: https://github.com/rust-lang/rust/pull/128147 [PR-128807]: https://github.com/rust-lang/rust/pull/128807 [PR-142841]: https://github.com/rust-lang/rust/pull/142841 [PR-143669]: https://github.com/rust-lang/rust/pull/143669 --- tests/run-make/fmt-write-bloat/main.rs | 32 ---------------------- tests/run-make/fmt-write-bloat/rmake.rs | 35 ------------------------- 2 files changed, 67 deletions(-) delete mode 100644 tests/run-make/fmt-write-bloat/main.rs delete mode 100644 tests/run-make/fmt-write-bloat/rmake.rs diff --git a/tests/run-make/fmt-write-bloat/main.rs b/tests/run-make/fmt-write-bloat/main.rs deleted file mode 100644 index b50461c0a0279..0000000000000 --- a/tests/run-make/fmt-write-bloat/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(lang_items)] -#![no_main] -#![no_std] - -use core::fmt; -use core::fmt::Write; - -#[cfg_attr(not(windows), link(name = "c"))] -extern "C" {} - -struct Dummy; - -impl fmt::Write for Dummy { - #[inline(never)] - fn write_str(&mut self, _: &str) -> fmt::Result { - Ok(()) - } -} - -#[no_mangle] -extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { - let _ = writeln!(Dummy, "Hello World"); - 0 -} - -#[lang = "eh_personality"] -fn eh_personality() {} - -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs deleted file mode 100644 index b7f18b384cb00..0000000000000 --- a/tests/run-make/fmt-write-bloat/rmake.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! Before #78122, writing any `fmt::Arguments` would trigger the inclusion of `usize` formatting -//! and padding code in the resulting binary, because indexing used in `fmt::write` would generate -//! code using `panic_bounds_check`, which prints the index and length. -//! -//! These bounds checks are not necessary, as `fmt::Arguments` never contains any out-of-bounds -//! indexes. The test is a `run-make` test, because it needs to check the result after linking. A -//! codegen or assembly test doesn't check the parts that will be pulled in from `core` by the -//! linker. -//! -//! In this test, we try to check that the `usize` formatting and padding code are not present in -//! the final binary by checking that panic symbols such as `panic_bounds_check` are **not** -//! present. -//! -//! Some CI jobs try to run faster by disabling debug assertions (through setting -//! `NO_DEBUG_ASSERTIONS=1`). If debug assertions are disabled, then we can check for the absence of -//! additional `usize` formatting and padding related symbols. - -//@ ignore-cross-compile - -use run_make_support::artifact_names::bin_name; -use run_make_support::env::std_debug_assertions_enabled; -use run_make_support::rustc; -use run_make_support::symbols::object_contains_any_symbol_substring; - -fn main() { - rustc().input("main.rs").opt().run(); - // panic machinery identifiers, these should not appear in the final binary - let mut panic_syms = vec!["panic_bounds_check", "Debug"]; - if std_debug_assertions_enabled() { - // if debug assertions are allowed, we need to allow these, - // otherwise, add them to the list of symbols to deny. - panic_syms.extend_from_slice(&["panicking", "panic_fmt", "pad_integral", "Display"]); - } - assert!(!object_contains_any_symbol_substring(bin_name("main"), &panic_syms)); -} From 3d035505a3e24830e6da84d31d7f63b02b6d5ae0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 2 Nov 2025 12:33:38 +0000 Subject: [PATCH 12/12] Better warning message for crate type unsupported by codegen backend --- compiler/rustc_driver_impl/src/lib.rs | 8 ++++++-- compiler/rustc_interface/src/passes.rs | 1 + compiler/rustc_session/messages.ftl | 3 +++ compiler/rustc_session/src/errors.rs | 7 +++++++ compiler/rustc_session/src/output.rs | 14 ++++++++------ 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c926a7c742a0a..462ca98c21151 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -686,8 +686,12 @@ fn print_crate_info( }; let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let crate_name = passes::get_crate_name(sess, attrs); - let crate_types = - collect_crate_types(sess, &codegen_backend.supported_crate_types(sess), attrs); + let crate_types = collect_crate_types( + sess, + &codegen_backend.supported_crate_types(sess), + codegen_backend.name(), + attrs, + ); for &style in &crate_types { let fname = rustc_session::output::filename_for_input( sess, style, crate_name, &t_outputs, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 58ed71a970776..e68db4f44ca48 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -929,6 +929,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let crate_types = collect_crate_types( sess, &compiler.codegen_backend.supported_crate_types(sess), + compiler.codegen_backend.name(), &pre_configured_attrs, ); let stable_crate_id = StableCrateId::new( diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b46e8ab4fdcbe..a4166951e350a 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -140,6 +140,9 @@ session_unleashed_feature_help_unnamed = skipping check that does not even have session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` +session_unsupported_crate_type_for_codegen_backend = + dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}` + session_unsupported_crate_type_for_target = dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 50bc7348dc9ef..07b41a3de714d 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -371,6 +371,13 @@ struct BinaryFloatLiteralNotSupported { span: Span, } +#[derive(Diagnostic)] +#[diag(session_unsupported_crate_type_for_codegen_backend)] +pub(crate) struct UnsupportedCrateTypeForCodegenBackend { + pub(crate) crate_type: CrateType, + pub(crate) codegen_backend: &'static str, +} + #[derive(Diagnostic)] #[diag(session_unsupported_crate_type_for_target)] pub(crate) struct UnsupportedCrateTypeForTarget<'a> { diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index a48a4f649da1d..99c736c3b1a5e 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -177,6 +177,7 @@ pub fn categorize_crate_type(s: Symbol) -> Option { pub fn collect_crate_types( session: &Session, backend_crate_types: &[CrateType], + codegen_backend_name: &'static str, attrs: &[ast::Attribute], ) -> Vec { // If we're generating a test executable, then ignore all other output @@ -223,17 +224,18 @@ pub fn collect_crate_types( } base.retain(|crate_type| { - if invalid_output_for_target(session, *crate_type) - || !backend_crate_types.contains(crate_type) - { - // FIXME provide a better warning for the case where the codegen - // backend doesn't support it once cargo doesn't hard code this - // warning message. + if invalid_output_for_target(session, *crate_type) { session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { crate_type: *crate_type, target_triple: &session.opts.target_triple, }); false + } else if !backend_crate_types.contains(crate_type) { + session.dcx().emit_warn(errors::UnsupportedCrateTypeForCodegenBackend { + crate_type: *crate_type, + codegen_backend: codegen_backend_name, + }); + false } else { true }