From 12e66289778bd712d9fe6268b130b45861d7a58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 16:01:11 +0100 Subject: [PATCH] Port rustc_nonnull_optimization_guaranteed to the new attribute parser --- .../rustc_attr_parsing/src/attributes/rustc_internal.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_const_eval/src/interpret/call.rs | 8 ++++++-- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_lint/src/types.rs | 5 +++-- compiler/rustc_passes/src/check_attr.rs | 2 +- tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs | 4 +++- 8 files changed, 27 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 40ab0e616752..fa0611bd8358 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1193,6 +1193,15 @@ impl NoArgsAttributeParser for RustcDoNotConstCheckParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck; } +pub(crate) struct RustcNonnullOptimizationGuaranteedParser; + +impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser { + const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed; +} + pub(crate) struct RustcSymbolName; impl SingleAttributeParser for RustcSymbolName { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 7ad74761cf70..1bb6c8aa1866 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -296,6 +296,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index b17740f57f78..7076aa94fc57 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -7,11 +7,12 @@ use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_data_structures::assert_matches; use rustc_errors::msg; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::find_attr; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; -use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use tracing::field::Empty; use tracing::{info, instrument, trace}; @@ -145,7 +146,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Check if the inner type is one of the NPO-guaranteed ones. // For that we first unpeel transparent *structs* (but not unions). let is_npo = |def: AdtDef<'tcx>| { - self.tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed) + find_attr!( + self.tcx.get_all_attrs(def.did()), + AttributeKind::RustcNonnullOptimizationGuaranteed + ) }; let inner = self.unfold_transparent(inner, /* may_unfold */ |def| { // Stop at NPO types so that we don't miss that attribute in the check below! diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 2a11518aaa79..41970fb7d35a 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1268,6 +1268,9 @@ pub enum AttributeKind { /// Represents `#[rustc_non_const_trait_method]`. RustcNonConstTraitMethod, + /// Represents `#[rustc_nonnull_optimization_guaranteed]`. + RustcNonnullOptimizationGuaranteed, + /// Represents `#[rustc_nounwind]` RustcNounwind, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 8fe70efc23d6..c50a5c649ee4 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -149,6 +149,7 @@ impl AttributeKind { RustcNoImplicitBounds => No, RustcNoMirInline => Yes, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` + RustcNonnullOptimizationGuaranteed => Yes, RustcNounwind => No, RustcObjcClass { .. } => No, RustcObjcSelector { .. } => No, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 47e1fef8b82e..b5126fffc1c5 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,7 +1,8 @@ use std::iter; use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange}; -use rustc_hir::{Expr, ExprKind, HirId, LangItem}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{Expr, ExprKind, HirId, LangItem, find_attr}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; @@ -686,7 +687,7 @@ pub(crate) fn nonnull_optimization_guaranteed<'tcx>( tcx: TyCtxt<'tcx>, def: ty::AdtDef<'tcx>, ) -> bool { - tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed) + find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::RustcNonnullOptimizationGuaranteed) } /// `repr(transparent)` structs can have a single non-1-ZST field, this function returns that diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5059c7c1c0be..ec0306371205 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -342,6 +342,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcNoImplicitBounds | AttributeKind::RustcNoMirInline | AttributeKind::RustcNonConstTraitMethod + | AttributeKind::RustcNonnullOptimizationGuaranteed | AttributeKind::RustcNounwind | AttributeKind::RustcObjcClass { .. } | AttributeKind::RustcObjcSelector { .. } @@ -399,7 +400,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::forbid // internal | sym::default_lib_allocator - | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks | sym::rustc_on_unimplemented | sym::rustc_doc_primitive diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs index f3d5bcbd8d78..beddfd87a5e7 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -5,10 +5,12 @@ //~| NOTE the `#[rustc_nonnull_optimization_guaranteed]` attribute is an internal implementation detail that will never be stable //~| NOTE the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in the standard library //~| NOTE the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized -fn main() {} +struct Foo {} #[rustc_variance] //~^ ERROR use of an internal attribute [E0658] //~| NOTE the `#[rustc_variance]` attribute is an internal implementation detail that will never be stable //~| NOTE the `#[rustc_variance]` attribute is used for rustc unit tests enum E {} + +fn main() {}