From d2e8aaa42fd3a2107fecbfc700863469909fc996 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 12 Jan 2026 17:16:49 +0100 Subject: [PATCH 01/12] std: use `ByteStr`'s `Display` for `OsStr` --- library/std/src/sys/os_str/bytes.rs | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index 7ba6c46eaef4e..5482663ef0079 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -4,8 +4,8 @@ use core::clone::CloneToUninit; use crate::borrow::Cow; +use crate::bstr::ByteStr; use crate::collections::TryReserveError; -use crate::fmt::Write; use crate::rc::Rc; use crate::sync::Arc; use crate::sys::{AsInner, FromInner, IntoInner}; @@ -64,25 +64,7 @@ impl fmt::Debug for Slice { impl fmt::Display for Slice { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If we're the empty string then our iterator won't actually yield - // anything, so perform the formatting manually - if self.inner.is_empty() { - return "".fmt(f); - } - - for chunk in self.inner.utf8_chunks() { - let valid = chunk.valid(); - // If we successfully decoded the whole chunk as a valid string then - // we can return a direct formatting of the string which will also - // respect various formatting flags if possible. - if chunk.invalid().is_empty() { - return valid.fmt(f); - } - - f.write_str(valid)?; - f.write_char(char::REPLACEMENT_CHARACTER)?; - } - Ok(()) + fmt::Display::fmt(ByteStr::new(&self.inner), f) } } From ed7479c658484647858e08342a9aa00aa0fb5b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 14 Jan 2026 21:47:24 +0100 Subject: [PATCH 02/12] Add the GCC codegen backend to build-manifest --- src/tools/build-manifest/src/main.rs | 3 ++- src/tools/build-manifest/src/versions.rs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 4cec1b1f164b9..7c0c528bcc049 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -32,7 +32,7 @@ static DOCS_FALLBACK: &[(&str, &str)] = &[ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin"]; static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = - &[PkgType::Miri, PkgType::JsonDocs, PkgType::RustcCodegenCranelift]; + &[PkgType::Miri, PkgType::JsonDocs, PkgType::RustcCodegenCranelift, PkgType::RustcCodegenGcc]; macro_rules! t { ($e:expr) => { @@ -302,6 +302,7 @@ impl Builder { | PkgType::RustAnalysis | PkgType::JsonDocs | PkgType::RustcCodegenCranelift + | PkgType::RustcCodegenGcc | PkgType::LlvmBitcodeLinker => { extensions.push(host_component(pkg)); } diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 6ef8a0e83de3f..1e55d1d467e66 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -59,6 +59,7 @@ pkg_type! { JsonDocs = "rust-docs-json"; preview = true, RustcCodegenCranelift = "rustc-codegen-cranelift"; preview = true, LlvmBitcodeLinker = "llvm-bitcode-linker"; preview = true, + RustcCodegenGcc = "rustc-codegen-gcc"; preview = true, } impl PkgType { @@ -82,6 +83,7 @@ impl PkgType { PkgType::LlvmTools => false, PkgType::Miri => false, PkgType::RustcCodegenCranelift => false, + PkgType::RustcCodegenGcc => false, PkgType::Rust => true, PkgType::RustStd => true, @@ -111,6 +113,7 @@ impl PkgType { RustcDocs => HOSTS, Cargo => HOSTS, RustcCodegenCranelift => HOSTS, + RustcCodegenGcc => HOSTS, RustMingw => MINGW, RustStd => TARGETS, HtmlDocs => HOSTS, From 4ceb13807e8062d5a4a3e9adecbd1d42a61eecf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 14 Jan 2026 21:49:44 +0100 Subject: [PATCH 03/12] Forbid distributing GCC on CI if `gcc.download-ci-gcc` is enabled --- src/bootstrap/src/core/build_steps/dist.rs | 10 +++++++++- src/bootstrap/src/core/config/mod.rs | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index cfcb144e0993e..bfffc958f858c 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -30,7 +30,7 @@ use crate::core::build_steps::tool::{ use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor}; use crate::core::build_steps::{compile, llvm}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata}; -use crate::core::config::TargetSelection; +use crate::core::config::{GccCiMode, TargetSelection}; use crate::utils::build_stamp::{self, BuildStamp}; use crate::utils::channel::{self, Info}; use crate::utils::exec::{BootstrapCommand, command}; @@ -3035,6 +3035,14 @@ impl Step for Gcc { return None; } + if builder.config.is_running_on_ci { + assert_eq!( + builder.config.gcc_ci_mode, + GccCiMode::BuildLocally, + "Cannot use gcc.download-ci-gcc when distributing GCC on CI" + ); + } + // We need the GCC sources to build GCC and also to add its license and README // files to the tarball builder.require_submodule( diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index 007ed4aaba13f..7651def62672a 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -425,7 +425,7 @@ impl std::str::FromStr for RustcLto { } /// Determines how will GCC be provided. -#[derive(Default, Clone)] +#[derive(Default, Debug, Clone, PartialEq)] pub enum GccCiMode { /// Build GCC from the local `src/gcc` submodule. BuildLocally, From ea9b062a8a71d16f8327ddf7d9ceac405a9a3bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 15 Jan 2026 11:15:26 +0100 Subject: [PATCH 04/12] Add GCC to build-manifest --- src/tools/build-manifest/src/main.rs | 7 +-- src/tools/build-manifest/src/versions.rs | 56 +++++++++++++++++++----- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 7c0c528bcc049..cd6efad011411 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -158,7 +158,7 @@ impl Builder { } fn add_packages_to(&mut self, manifest: &mut Manifest) { - for pkg in PkgType::all() { + for pkg in &PkgType::all() { self.package(pkg, &mut manifest.pkg); } } @@ -227,7 +227,7 @@ impl Builder { }; for pkg in PkgType::all() { if pkg.is_preview() { - rename(pkg.tarball_component_name(), &pkg.manifest_component_name()); + rename(&pkg.tarball_component_name(), &pkg.manifest_component_name()); } } } @@ -263,7 +263,7 @@ impl Builder { let host_component = |pkg: &_| Component::from_pkg(pkg, host); - for pkg in PkgType::all() { + for pkg in &PkgType::all() { match pkg { // rustc/rust-std/cargo/docs are all required PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => { @@ -303,6 +303,7 @@ impl Builder { | PkgType::JsonDocs | PkgType::RustcCodegenCranelift | PkgType::RustcCodegenGcc + | PkgType::Gcc { .. } | PkgType::LlvmBitcodeLinker => { extensions.push(host_component(pkg)); } diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs index 1e55d1d467e66..b53f6c5edc5d9 100644 --- a/src/tools/build-manifest/src/versions.rs +++ b/src/tools/build-manifest/src/versions.rs @@ -11,29 +11,54 @@ use xz2::read::XzDecoder; const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu"; macro_rules! pkg_type { - ( $($variant:ident = $component:literal $(; preview = true $(@$is_preview:tt)? )? ),+ $(,)? ) => { + ( $($variant:ident = $component:literal $(; preview = true $(@$is_preview:tt)? )? $(; suffixes = [$($suffixes:literal),+] $(@$is_suffixed:tt)? )? ),+ $(,)? ) => { #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub(crate) enum PkgType { - $($variant,)+ + $($variant $( $($is_suffixed)? { suffix: &'static str })?,)+ } impl PkgType { pub(crate) fn is_preview(&self) -> bool { match self { - $( $( $($is_preview)? PkgType::$variant => true, )? )+ - _ => false, + $( PkgType::$variant $($($is_suffixed)? { .. })? => false $( $($is_preview)? || true)?, )+ } } - /// First part of the tarball name. - pub(crate) fn tarball_component_name(&self) -> &str { + /// First part of the tarball name. May include a suffix, if the package has one. + pub(crate) fn tarball_component_name(&self) -> String { match self { - $( PkgType::$variant => $component,)+ + $( PkgType::$variant $($($is_suffixed)? { suffix })? => { + #[allow(unused_mut)] + let mut name = $component.to_owned(); + $($($is_suffixed)? + name.push('-'); + name.push_str(suffix); + )? + name + },)+ } } - pub(crate) fn all() -> &'static [PkgType] { - &[ $(PkgType::$variant),+ ] + pub(crate) fn all() -> Vec { + let mut packages = vec![]; + $( + // Push the single variant + packages.push(PkgType::$variant $($($is_suffixed)? { suffix: "" })?); + // Macro hell, we have to remove the fake empty suffix if we actually have + // suffixes + $( + $($is_suffixed)? + packages.pop(); + )? + // And now add the suffixes, if any + $( + $($is_suffixed)? + $( + packages.push(PkgType::$variant { suffix: $suffixes }); + )+ + )? + )+ + packages } } } @@ -60,6 +85,9 @@ pkg_type! { RustcCodegenCranelift = "rustc-codegen-cranelift"; preview = true, LlvmBitcodeLinker = "llvm-bitcode-linker"; preview = true, RustcCodegenGcc = "rustc-codegen-gcc"; preview = true, + Gcc = "gcc"; preview = true; suffixes = [ + "x86_64-unknown-linux-gnu" + ], } impl PkgType { @@ -68,7 +96,7 @@ impl PkgType { if self.is_preview() { format!("{}-preview", self.tarball_component_name()) } else { - self.tarball_component_name().to_string() + self.tarball_component_name() } } @@ -84,6 +112,7 @@ impl PkgType { PkgType::Miri => false, PkgType::RustcCodegenCranelift => false, PkgType::RustcCodegenGcc => false, + PkgType::Gcc { suffix: _ } => false, PkgType::Rust => true, PkgType::RustStd => true, @@ -114,6 +143,13 @@ impl PkgType { Cargo => HOSTS, RustcCodegenCranelift => HOSTS, RustcCodegenGcc => HOSTS, + // Gcc is "special", because we need a separate libgccjit.so for each + // (host, target) compilation pair. So it's even more special than stdlib, which has a + // separate component per target. This component thus hardcodes its compilation + // target in its name, and we thus ship it for HOSTS only. So we essentially have + // gcc-T1, gcc-T2, a separate *component/package* per each compilation target. + // So on host T1, if you want to compile for T2, you would install gcc-T2. + Gcc { suffix: _ } => HOSTS, RustMingw => MINGW, RustStd => TARGETS, HtmlDocs => HOSTS, From f4834cf52e38ffac51d1a2a6d47257013c4e84d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 21 Jan 2026 09:44:18 +0100 Subject: [PATCH 05/12] Make the GCC component as nightly only in build-manifest --- src/tools/build-manifest/src/main.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index cd6efad011411..946962832aef4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -31,8 +31,16 @@ static DOCS_FALLBACK: &[(&str, &str)] = &[ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin"]; -static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = - &[PkgType::Miri, PkgType::JsonDocs, PkgType::RustcCodegenCranelift, PkgType::RustcCodegenGcc]; +fn is_nightly_only(pkg: &PkgType) -> bool { + match pkg { + PkgType::Miri + | PkgType::JsonDocs + | PkgType::RustcCodegenCranelift + | PkgType::RustcCodegenGcc + | PkgType::Gcc { .. } => true, + _ => false, + } +} macro_rules! t { ($e:expr) => { @@ -375,7 +383,7 @@ impl Builder { let mut is_present = version_info.present; // Never ship nightly-only components for other trains. - if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkg) { + if self.versions.channel() != "nightly" && is_nightly_only(&pkg) { is_present = false; // Pretend the component is entirely missing. } From 4131674f49e6707e67197a03f7e7b94d3eac2b3a Mon Sep 17 00:00:00 2001 From: enthropy7 <221884178+enthropy7@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:31:22 +0300 Subject: [PATCH 06/12] Fix ICE when using function pointer as const generic parameter --- .../src/hir_ty_lowering/generics.rs | 9 ++--- tests/crashes/137084.rs | 6 ---- .../fn-item-as-const-arg-137084.rs | 14 ++++++++ .../fn-item-as-const-arg-137084.stderr | 35 +++++++++++++++++++ .../ice-151186-fn-ptr-in-where-clause.rs | 16 +++++++++ .../ice-151186-fn-ptr-in-where-clause.stderr | 22 ++++++++++++ 6 files changed, 90 insertions(+), 12 deletions(-) delete mode 100644 tests/crashes/137084.rs create mode 100644 tests/ui/const-generics/fn-item-as-const-arg-137084.rs create mode 100644 tests/ui/const-generics/fn-item-as-const-arg-137084.stderr create mode 100644 tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs create mode 100644 tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index f5a64ede398ea..8f9c8821b998a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -609,13 +609,10 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( position: GenericArgPosition, ) -> ExplicitLateBound { let param_counts = def.own_counts(); - let infer_lifetimes = position != GenericArgPosition::Type && !args.has_lifetime_params(); - if infer_lifetimes { - return ExplicitLateBound::No; - } - - if let Some(span_late) = def.has_late_bound_regions { + if let Some(span_late) = def.has_late_bound_regions + && args.has_lifetime_params() + { let msg = "cannot specify lifetime arguments explicitly \ if late bound lifetime parameters are present"; let note = "the late bound lifetime parameter is introduced here"; diff --git a/tests/crashes/137084.rs b/tests/crashes/137084.rs deleted file mode 100644 index 0f248c2120628..0000000000000 --- a/tests/crashes/137084.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #137084 -#![feature(min_generic_const_args)] -fn a() {} -fn d(e: &String) { - a:: -} diff --git a/tests/ui/const-generics/fn-item-as-const-arg-137084.rs b/tests/ui/const-generics/fn-item-as-const-arg-137084.rs new file mode 100644 index 0000000000000..8b75a3c8c96d1 --- /dev/null +++ b/tests/ui/const-generics/fn-item-as-const-arg-137084.rs @@ -0,0 +1,14 @@ +// Regression test for https://github.com/rust-lang/rust/issues/137084 +// Previously caused ICE when using function item as const generic argument + +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +fn a() {} +fn d(e: &String) { + a:: + //~^ ERROR mismatched types + //~| ERROR the constant `d` is not of type `i32` +} + +fn main() {} diff --git a/tests/ui/const-generics/fn-item-as-const-arg-137084.stderr b/tests/ui/const-generics/fn-item-as-const-arg-137084.stderr new file mode 100644 index 0000000000000..58b74c655cd23 --- /dev/null +++ b/tests/ui/const-generics/fn-item-as-const-arg-137084.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/fn-item-as-const-arg-137084.rs:9:5 + | +LL | fn a() {} + | -------------------- function `a` defined here +LL | fn d(e: &String) { +LL | a:: + | ^^^^^^ expected `()`, found fn item + | + = note: expected unit type `()` + found fn item `fn() {a::}` +help: try adding a return type + | +LL | fn d(e: &String) -> fn() { + | +++++++ +help: use parentheses to call this function + | +LL | a::() + | ++ + +error: the constant `d` is not of type `i32` + --> $DIR/fn-item-as-const-arg-137084.rs:9:9 + | +LL | a:: + | ^ expected `i32`, found fn item + | +note: required by a const generic parameter in `a` + --> $DIR/fn-item-as-const-arg-137084.rs:7:6 + | +LL | fn a() {} + | ^^^^^^^^^^^^ required by this const generic parameter in `a` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs new file mode 100644 index 0000000000000..7710fc68d7957 --- /dev/null +++ b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs @@ -0,0 +1,16 @@ +// Regression test for https://github.com/rust-lang/rust/issues/151186 + +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +trait Maybe {} + +trait MyTrait ()> {} +//~^ ERROR using function pointers as const generic parameters is forbidden + +fn foo<'a>(x: &'a ()) -> &'a () { x } + +impl Maybe for T where T: MyTrait<{ foo }> {} +//~^ ERROR the constant `foo` is not of type `fn()` + +fn main() {} diff --git a/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.stderr b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.stderr new file mode 100644 index 0000000000000..7c9d7ee7dde59 --- /dev/null +++ b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.stderr @@ -0,0 +1,22 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/ice-151186-fn-ptr-in-where-clause.rs:8:24 + | +LL | trait MyTrait ()> {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: the constant `foo` is not of type `fn()` + --> $DIR/ice-151186-fn-ptr-in-where-clause.rs:13:33 + | +LL | impl Maybe for T where T: MyTrait<{ foo }> {} + | ^^^^^^^^^^^^^^^^ expected fn pointer, found fn item + | +note: required by a const generic parameter in `MyTrait` + --> $DIR/ice-151186-fn-ptr-in-where-clause.rs:8:15 + | +LL | trait MyTrait ()> {} + | ^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `MyTrait` + +error: aborting due to 2 previous errors + From 1521f88c90a413c52f935bfc57ea0535e5a47c99 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Wed, 21 Jan 2026 16:30:22 +0000 Subject: [PATCH 07/12] add x86_64-unknown-linux-gnuasan to CI Since it is a tier 2 target it should also be built by the CI workflow. --- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 90f46b5376e01..7c165e38f8f9d 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -113,6 +113,7 @@ ENV TARGETS=$TARGETS,wasm32-wasip1 ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,wasm32-wasip2 ENV TARGETS=$TARGETS,wasm32v1-none +ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnuasan ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda From 8c4e48e9b543353a9c944bda646cb85ba6cae3e6 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Sun, 18 Jan 2026 20:43:01 +0000 Subject: [PATCH 08/12] Port #![compiler_builtins] to the attribute parser. --- compiler/rustc_attr_parsing/src/attributes/link_attrs.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 6 ++++-- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 3 +-- 7 files changed, 20 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index ce3d116dce3ba..a636b449ca569 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -665,3 +665,12 @@ impl NoArgsAttributeParser for NeedsAllocatorParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } + +pub(crate) struct CompilerBuiltinsParser; + +impl NoArgsAttributeParser for CompilerBuiltinsParser { + const PATH: &[Symbol] = &[sym::compiler_builtins]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 614619bca3ec2..f1eb03915144b 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -40,8 +40,9 @@ use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::instruction_set::InstructionSetParser; use crate::attributes::link_attrs::{ - ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, - LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, StdInternalSymbolParser, + CompilerBuiltinsParser, ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, + LinkOrdinalParser, LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, + StdInternalSymbolParser, }; use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, @@ -251,6 +252,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 21f7c4ae7c108..7fab94ce2afe8 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -687,6 +687,9 @@ pub enum AttributeKind { /// Represents `#[collapse_debuginfo]`. CollapseDebugInfo(CollapseMacroDebuginfo), + /// Represents `#[compiler_builtins]`. + CompilerBuiltins, + /// Represents `#[rustc_confusables]`. Confusables { symbols: ThinVec, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 640554dc81cd6..d5487315630c7 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -32,6 +32,7 @@ impl AttributeKind { Coinductive(..) => No, Cold(..) => No, CollapseDebugInfo(..) => Yes, + CompilerBuiltins => No, Confusables { .. } => Yes, ConstContinue(..) => No, ConstStability { .. } => Yes, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5478e20842866..73c1f02e94ece 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -741,7 +741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { externally_implementable_items, proc_macro_data, debugger_visualizers, - compiler_builtins: ast::attr::contains_name(attrs, sym::compiler_builtins), + compiler_builtins: find_attr!(attrs, AttributeKind::CompilerBuiltins), needs_allocator: find_attr!(attrs, AttributeKind::NeedsAllocator), needs_panic_runtime: ast::attr::contains_name(attrs, sym::needs_panic_runtime), no_builtins: ast::attr::contains_name(attrs, sym::no_builtins), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2f7a31a957bc8..272881d1cbbee 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3562,7 +3562,7 @@ pub fn provide(providers: &mut Providers) { providers.is_panic_runtime = |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime); providers.is_compiler_builtins = - |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::compiler_builtins); + |tcx, LocalCrate| find_attr!(tcx.hir_krate_attrs(), AttributeKind::CompilerBuiltins); providers.has_panic_handler = |tcx, LocalCrate| { // We want to check if the panic handler was defined in this crate tcx.lang_items().panic_impl().is_some_and(|did| did.is_local()) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b6141bf7db535..659da307ab691 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -299,6 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::NoCore { .. } | AttributeKind::NoStd { .. } | AttributeKind::NoMain + | AttributeKind::CompilerBuiltins | AttributeKind::ObjcClass { .. } | AttributeKind::ObjcSelector { .. } | AttributeKind::RustcCoherenceIsCore(..) @@ -397,10 +398,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_no_implicit_bounds | sym::test_runner | sym::reexport_test_harness_main - | sym::no_main | sym::no_builtins | sym::crate_type - | sym::compiler_builtins | sym::profiler_runtime | sym::needs_panic_runtime | sym::panic_runtime From 1143cb2bb2c10609fe0a562b8aba817e843db74c Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Sun, 18 Jan 2026 21:08:17 +0000 Subject: [PATCH 09/12] Port two panic attrs to the attr parser. Ports #![panic_runtime] and #![needs_panic_runtime] --- .../src/attributes/crate_level.rs | 18 ++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 8 +++++--- .../rustc_hir/src/attrs/data_structures.rs | 6 ++++++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 2 ++ compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++-- compiler/rustc_middle/src/ty/context.rs | 10 +++------- compiler/rustc_passes/src/check_attr.rs | 4 ++-- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index ab99186777f92..95c3e6bdd708b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -184,3 +184,21 @@ impl SingleAttributeParser for WindowsSubsystemParser { Some(AttributeKind::WindowsSubsystem(kind, cx.attr_span)) } } + +pub(crate) struct PanicRuntimeParser; + +impl NoArgsAttributeParser for PanicRuntimeParser { + const PATH: &[Symbol] = &[sym::panic_runtime]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; +} + +pub(crate) struct NeedsPanicRuntimeParser; + +impl NoArgsAttributeParser for NeedsPanicRuntimeParser { + const PATH: &[Symbol] = &[sym::needs_panic_runtime]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f1eb03915144b..0bb0f5c5e22bd 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,9 +28,9 @@ use crate::attributes::codegen_attrs::{ }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::crate_level::{ - CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoMainParser, NoStdParser, - PatternComplexityLimitParser, RecursionLimitParser, RustcCoherenceIsCoreParser, - TypeLengthLimitParser, WindowsSubsystemParser, + CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoCoreParser, NoMainParser, + NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser, RecursionLimitParser, + RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, }; use crate::attributes::debugger::DebuggerViualizerParser; use crate::attributes::deprecation::DeprecationParser; @@ -268,6 +268,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, @@ -275,6 +276,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 7fab94ce2afe8..9eec151521b40 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -846,6 +846,9 @@ pub enum AttributeKind { /// Represents `#[needs_allocator]` NeedsAllocator, + /// Represents `#[needs_panic_runtime]` + NeedsPanicRuntime, + /// Represents `#[no_core]` NoCore(Span), @@ -876,6 +879,9 @@ pub enum AttributeKind { /// Represents `#[optimize(size|speed)]` Optimize(OptimizeAttr, Span), + /// Represents `#[panic_runtime]` + PanicRuntime, + /// Represents `#[rustc_paren_sugar]`. ParenSugar(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index d5487315630c7..36556c6e82620 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -77,6 +77,7 @@ impl AttributeKind { MustUse { .. } => Yes, Naked(..) => No, NeedsAllocator => No, + NeedsPanicRuntime => No, NoCore(..) => No, NoImplicitPrelude(..) => No, NoLink => No, @@ -87,6 +88,7 @@ impl AttributeKind { ObjcClass { .. } => No, ObjcSelector { .. } => No, Optimize(..) => No, + PanicRuntime => No, ParenSugar(..) => No, PassByValue(..) => Yes, PatchableFunctionEntry { .. } => Yes, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 73c1f02e94ece..c82e37e83a3c7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -743,9 +743,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debugger_visualizers, compiler_builtins: find_attr!(attrs, AttributeKind::CompilerBuiltins), needs_allocator: find_attr!(attrs, AttributeKind::NeedsAllocator), - needs_panic_runtime: ast::attr::contains_name(attrs, sym::needs_panic_runtime), + needs_panic_runtime: find_attr!(attrs, AttributeKind::NeedsPanicRuntime), no_builtins: ast::attr::contains_name(attrs, sym::no_builtins), - panic_runtime: ast::attr::contains_name(attrs, sym::panic_runtime), + panic_runtime: find_attr!(attrs, AttributeKind::PanicRuntime), profiler_runtime: ast::attr::contains_name(attrs, sym::profiler_runtime), symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 272881d1cbbee..6e68cb661e06a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -38,7 +38,7 @@ use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::lang_items::LangItem; use rustc_hir::limit::Limit; -use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate, find_attr}; +use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr}; use rustc_index::IndexVec; use rustc_query_system::cache::WithDepNode; use rustc_query_system::dep_graph::DepNodeIndex; @@ -49,7 +49,7 @@ use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use rustc_type_ir::TyKind::*; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; pub use rustc_type_ir::lift::Lift; @@ -3560,7 +3560,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provide(providers: &mut Providers) { providers.is_panic_runtime = - |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime); + |tcx, LocalCrate| find_attr!(tcx.hir_krate_attrs(), AttributeKind::PanicRuntime); providers.is_compiler_builtins = |tcx, LocalCrate| find_attr!(tcx.hir_krate_attrs(), AttributeKind::CompilerBuiltins); providers.has_panic_handler = |tcx, LocalCrate| { @@ -3569,7 +3569,3 @@ pub fn provide(providers: &mut Providers) { }; providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP); } - -pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool { - attrs.iter().any(|x| x.has_name(name)) -} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 659da307ab691..71c4c2b39bce6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -300,6 +300,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::NoStd { .. } | AttributeKind::NoMain | AttributeKind::CompilerBuiltins + | AttributeKind::PanicRuntime + | AttributeKind::NeedsPanicRuntime | AttributeKind::ObjcClass { .. } | AttributeKind::ObjcSelector { .. } | AttributeKind::RustcCoherenceIsCore(..) @@ -401,8 +403,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::no_builtins | sym::crate_type | sym::profiler_runtime - | sym::needs_panic_runtime - | sym::panic_runtime | sym::rustc_preserve_ub_checks, .. ] => {} From 54385b52b4402543f5c03128b114ed39bcae33af Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Sun, 18 Jan 2026 21:21:28 +0000 Subject: [PATCH 10/12] Port #![profiler_runtime] to the attribute parser. --- .../rustc_attr_parsing/src/attributes/crate_level.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 5 +++-- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 95c3e6bdd708b..b3b4f12fd152b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -202,3 +202,12 @@ impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } + +pub(crate) struct ProfilerRuntimeParser; + +impl NoArgsAttributeParser for ProfilerRuntimeParser { + const PATH: &[Symbol] = &[sym::profiler_runtime]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0bb0f5c5e22bd..7f637ffe6389f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,8 +28,8 @@ use crate::attributes::codegen_attrs::{ }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::crate_level::{ - CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoCoreParser, NoMainParser, - NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser, RecursionLimitParser, + CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoCoreParser, NoMainParser, NoStdParser, + PanicRuntimeParser, PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, }; use crate::attributes::debugger::DebuggerViualizerParser; @@ -283,6 +283,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 9eec151521b40..4cfa6f5996c4b 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -912,6 +912,9 @@ pub enum AttributeKind { /// Represents `#[proc_macro_derive]` ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec, span: Span }, + /// Represents `#[profiler_runtime]` + ProfilerRuntime, + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). PubTransparent(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 36556c6e82620..6a7a3561c97dd 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -99,6 +99,7 @@ impl AttributeKind { ProcMacro(..) => No, ProcMacroAttribute(..) => No, ProcMacroDerive { .. } => No, + ProfilerRuntime => No, PubTransparent(..) => Yes, RecursionLimit { .. } => No, Repr { .. } => No, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c82e37e83a3c7..5b88ab26c55c1 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -746,7 +746,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { needs_panic_runtime: find_attr!(attrs, AttributeKind::NeedsPanicRuntime), no_builtins: ast::attr::contains_name(attrs, sym::no_builtins), panic_runtime: find_attr!(attrs, AttributeKind::PanicRuntime), - profiler_runtime: ast::attr::contains_name(attrs, sym::profiler_runtime), + profiler_runtime: find_attr!(attrs, AttributeKind::ProfilerRuntime), symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 71c4c2b39bce6..3cd3059713229 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -302,6 +302,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::CompilerBuiltins | AttributeKind::PanicRuntime | AttributeKind::NeedsPanicRuntime + | AttributeKind::ProfilerRuntime | AttributeKind::ObjcClass { .. } | AttributeKind::ObjcSelector { .. } | AttributeKind::RustcCoherenceIsCore(..) @@ -402,7 +403,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::reexport_test_harness_main | sym::no_builtins | sym::crate_type - | sym::profiler_runtime | sym::rustc_preserve_ub_checks, .. ] => {} From f6d76385e239f24d3005f3c076dc6df826bbd97d Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Sun, 18 Jan 2026 21:55:42 +0000 Subject: [PATCH 11/12] Port #![no_builtins] to the attribute parser. --- .../src/attributes/crate_level.rs | 9 ++ compiler/rustc_attr_parsing/src/context.rs | 8 +- compiler/rustc_codegen_ssa/src/back/write.rs | 7 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 4 +- .../rustc_hir/src/attrs/data_structures.rs | 3 + .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../issue-43106-gating-of-builtin-attrs.rs | 12 +- ...issue-43106-gating-of-builtin-attrs.stderr | 131 ++++++++++-------- .../lint/unused/unused-attr-duplicate.stderr | 24 ++-- 11 files changed, 114 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index b3b4f12fd152b..1829ced70c93f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -211,3 +211,12 @@ impl NoArgsAttributeParser for ProfilerRuntimeParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } + +pub(crate) struct NoBuiltinsParser; + +impl NoArgsAttributeParser for NoBuiltinsParser { + const PATH: &[Symbol] = &[sym::no_builtins]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 7f637ffe6389f..2febcd6559912 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,9 +28,10 @@ use crate::attributes::codegen_attrs::{ }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::crate_level::{ - CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoCoreParser, NoMainParser, NoStdParser, - PanicRuntimeParser, PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, - RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, + CrateNameParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoBuiltinsParser, NoCoreParser, + NoMainParser, NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser, + ProfilerRuntimeParser, RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser, + WindowsSubsystemParser, }; use crate::attributes::debugger::DebuggerViualizerParser; use crate::attributes::deprecation::DeprecationParser; @@ -269,6 +270,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index af9c61e177682..8321f7fde503f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -6,7 +6,6 @@ use std::sync::mpsc::{Receiver, Sender, channel}; use std::{fs, io, mem, str, thread}; use rustc_abi::Size; -use rustc_ast::attr; use rustc_data_structures::assert_matches; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::jobserver::{self, Acquired}; @@ -19,6 +18,8 @@ use rustc_errors::{ Level, MultiSpan, Style, Suggestions, catch_fatal_errors, }; use rustc_fs_util::link_or_copy; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_incremental::{ copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; @@ -31,7 +32,7 @@ use rustc_session::config::{ self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath, }; use rustc_span::source_map::SourceMap; -use rustc_span::{FileName, InnerSpan, Span, SpanData, sym}; +use rustc_span::{FileName, InnerSpan, Span, SpanData}; use rustc_target::spec::{MergeFunctions, SanitizerSet}; use tracing::debug; @@ -453,7 +454,7 @@ pub(crate) fn start_async_codegen( let (coordinator_send, coordinator_receive) = channel(); let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID); - let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); + let no_builtins = find_attr!(crate_attrs, AttributeKind::NoBuiltins); let crate_info = CrateInfo::new(tcx, target_cpu); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d55e134109d66..4cb390e7d5699 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; -use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; +use rustc_ast::{LitKind, MetaItem, MetaItemInner}; use rustc_hir::attrs::{ AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy, }; @@ -353,7 +353,7 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code // When `no_builtins` is applied at the crate level, we should add the // `no-builtins` attribute to each function to ensure it takes effect in LTO. let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID); - let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); + let no_builtins = find_attr!(crate_attrs, AttributeKind::NoBuiltins); if no_builtins { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS; } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 4cfa6f5996c4b..65b3c2ec2df7d 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -849,6 +849,9 @@ pub enum AttributeKind { /// Represents `#[needs_panic_runtime]` NeedsPanicRuntime, + /// Represents `#[no_builtins]` + NoBuiltins, + /// Represents `#[no_core]` NoCore(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 6a7a3561c97dd..739a5a6d0ea50 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -78,6 +78,7 @@ impl AttributeKind { Naked(..) => No, NeedsAllocator => No, NeedsPanicRuntime => No, + NoBuiltins => Yes, NoCore(..) => No, NoImplicitPrelude(..) => No, NoLink => No, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5b88ab26c55c1..471c19ed4d4e7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -744,7 +744,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { compiler_builtins: find_attr!(attrs, AttributeKind::CompilerBuiltins), needs_allocator: find_attr!(attrs, AttributeKind::NeedsAllocator), needs_panic_runtime: find_attr!(attrs, AttributeKind::NeedsPanicRuntime), - no_builtins: ast::attr::contains_name(attrs, sym::no_builtins), + no_builtins: find_attr!(attrs, AttributeKind::NoBuiltins), panic_runtime: find_attr!(attrs, AttributeKind::PanicRuntime), profiler_runtime: find_attr!(attrs, AttributeKind::ProfilerRuntime), symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3cd3059713229..ad1829802b8c5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -303,6 +303,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::PanicRuntime | AttributeKind::NeedsPanicRuntime | AttributeKind::ProfilerRuntime + | AttributeKind::NoBuiltins | AttributeKind::ObjcClass { .. } | AttributeKind::ObjcSelector { .. } | AttributeKind::RustcCoherenceIsCore(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_no_implicit_bounds | sym::test_runner | sym::reexport_test_harness_main - | sym::no_builtins | sym::crate_type | sym::rustc_preserve_ub_checks, .. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index ce2f9a4e6eebe..89c67325d6d16 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -908,26 +908,26 @@ mod no_main_1 { #[no_builtins] //~^ WARN crate-level attribute should be an inner attribute -//~| HELP add a `!` mod no_builtins { + //~^ NOTE: this attribute does not have an `!`, which means it is applied to this module mod inner { #![no_builtins] } - //~^ WARN crate-level attribute should be in the root module + //~^ WARN the `#![no_builtins]` attribute can only be used at the crate root #[no_builtins] fn f() { } //~^ WARN crate-level attribute should be an inner attribute - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this function #[no_builtins] struct S; //~^ WARN crate-level attribute should be an inner attribute - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this struct #[no_builtins] type T = S; //~^ WARN crate-level attribute should be an inner attribute - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this type alias #[no_builtins] impl S { } //~^ WARN crate-level attribute should be an inner attribute - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this implementation } #[recursion_limit="0200"] diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index cbb80ccd753cc..b0c1edeff8d93 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -240,17 +240,6 @@ help: add a `!` LL | #![feature(x0600)] | + -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:1 - | -LL | #[no_builtins] - | ^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![no_builtins] - | + - warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1 | @@ -465,56 +454,6 @@ help: add a `!` LL | #![feature(x0600)] impl S { } | + -warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:17 - | -LL | mod inner { #![no_builtins] } - | ^^^^^^^^^^^^^^^ - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:5 - | -LL | #[no_builtins] fn f() { } - | ^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![no_builtins] fn f() { } - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:5 - | -LL | #[no_builtins] struct S; - | ^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![no_builtins] struct S; - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:924:5 - | -LL | #[no_builtins] type T = S; - | ^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![no_builtins] type T = S; - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:5 - | -LL | #[no_builtins] impl S { } - | ^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![no_builtins] impl S { } - | + - warning: `#[macro_use]` attribute cannot be used on functions --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5 | @@ -1416,6 +1355,76 @@ note: this attribute does not have an `!`, which means it is applied to this imp LL | #[no_main] impl S { } | ^^^^^^^^^^ +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:1 + | +LL | #[no_builtins] + | ^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:911:1 + | +LL | / mod no_builtins { +LL | | +LL | | mod inner { #![no_builtins] } +... | +LL | | } + | |_^ + +warning: the `#![no_builtins]` attribute can only be used at the crate root + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:17 + | +LL | mod inner { #![no_builtins] } + | ^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:5 + | +LL | #[no_builtins] fn f() { } + | ^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:20 + | +LL | #[no_builtins] fn f() { } + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:5 + | +LL | #[no_builtins] struct S; + | ^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this struct + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:20 + | +LL | #[no_builtins] struct S; + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:924:5 + | +LL | #[no_builtins] type T = S; + | ^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this type alias + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:924:20 + | +LL | #[no_builtins] type T = S; + | ^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:5 + | +LL | #[no_builtins] impl S { } + | ^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this implementation block + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:20 + | +LL | #[no_builtins] impl S { } + | ^^^^^^^^^^ + warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:1 | diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 54ed351d43486..351645f4a783f 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -16,18 +16,6 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:34:1 - | -LL | #![no_builtins] - | ^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:33:1 - | -LL | #![no_builtins] - | ^^^^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:37:1 | @@ -316,5 +304,17 @@ LL | #![windows_subsystem = "console"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:34:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:33:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ + error: aborting due to 25 previous errors From a509588fa983e16452df3fa5c81aaf853907a78b Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Tue, 13 Jan 2026 20:46:14 -0500 Subject: [PATCH 12/12] feat: support slices in reflection type info --- .../src/const_eval/type_info.rs | 30 ++++++++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/mem/type_info.rs | 11 +++++++ library/coretests/tests/mem/type_info.rs | 8 +++++ tests/ui/reflection/dump.bit32.run.stdout | 6 +++- tests/ui/reflection/dump.bit64.run.stdout | 6 +++- 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index e6092fc3787c6..3fcf6f94b5bf3 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -66,6 +66,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } + ty::Slice(ty) => { + let (variant, variant_place) = downcast(sym::Slice)?; + let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + self.write_slice_type_info(slice_place, *ty)?; + + variant + } ty::Bool => { let (variant, _variant_place) = downcast(sym::Bool)?; variant @@ -124,7 +132,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { ty::Adt(_, _) | ty::Foreign(_) | ty::Pat(_, _) - | ty::Slice(_) | ty::FnDef(..) | ty::FnPtr(..) | ty::UnsafeBinder(..) @@ -254,6 +261,27 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + pub(crate) fn write_slice_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + ty: Ty<'tcx>, + ) -> InterpResult<'tcx> { + // Iterate over all fields of `type_info::Slice`. + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + // Write the `TypeId` of the slice's elements to the `element_ty` field. + sym::element_ty => self.write_type_id(ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + fn write_int_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d6d6ebb49e106..5767444025ec2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -362,6 +362,7 @@ symbols! { Send, SeqCst, Sized, + Slice, SliceIndex, SliceIter, Some, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index d584523aebe2f..30a70165b095f 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -45,6 +45,8 @@ pub enum TypeKind { Tuple(Tuple), /// Arrays. Array(Array), + /// Slices. + Slice(Slice), /// Primitive boolean type. Bool(Bool), /// Primitive character type. @@ -94,6 +96,15 @@ pub struct Array { pub len: usize, } +/// Compile-time type information about slices. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Slice { + /// The type of each element in the slice. + pub element_ty: TypeId, +} + /// Compile-time type information about `bool`. #[derive(Debug)] #[non_exhaustive] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 816fbac32f20d..0820e4f839930 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -22,6 +22,14 @@ fn test_arrays() { } } +#[test] +fn test_slices() { + match const { Type::of::<[usize]>() }.kind { + TypeKind::Slice(slice) => assert_eq!(slice.element_ty, TypeId::of::()), + _ => unreachable!(), + } +} + #[test] fn test_tuples() { fn assert_tuple_arity() { diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index 0c8a835923be7..d15b46509ff20 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -194,7 +194,11 @@ Type { size: None, } Type { - kind: Other, + kind: Slice( + Slice { + element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + }, + ), size: None, } Type { diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index 20af4deb4e416..efae226539515 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -194,7 +194,11 @@ Type { size: None, } Type { - kind: Other, + kind: Slice( + Slice { + element_ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), + }, + ), size: None, } Type {