Rollup merge of #142964 - GrigorenkoPV:attributes/argless, r=oli-obk

Attribute rework: a parser for single attributes without arguments

Part of rust-lang/rust#131229

r? `@jdonszelmann`

I think code (with comments) speaks for itself.

The only subtlety: now `#[cold]`, `#[no_mangle]`, & `#[track_caller]` do not get thrown away when malformed (i.e. have arguments). This doesn't matter too much (I think), because an error gets emitted either way, so the compilation will not finish.
This commit is contained in:
Matthias Krüger
2025-07-02 19:29:36 +02:00
committed by GitHub
8 changed files with 91 additions and 132 deletions

View File

@@ -17,7 +17,7 @@
use std::marker::PhantomData;
use rustc_attr_data_structures::AttributeKind;
use rustc_feature::AttributeTemplate;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
@@ -229,6 +229,41 @@ pub(crate) enum AttributeOrder {
KeepLast,
}
/// An even simpler version of [`SingleAttributeParser`]:
/// now automatically check that there are no arguments provided to the attribute.
///
/// [`WithoutArgs<T> where T: NoArgsAttributeParser`](WithoutArgs) implements [`SingleAttributeParser`].
//
pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
const PATH: &[Symbol];
const ON_DUPLICATE: OnDuplicate<S>;
/// Create the [`AttributeKind`] given attribute's [`Span`].
const CREATE: fn(Span) -> AttributeKind;
}
pub(crate) struct WithoutArgs<T: NoArgsAttributeParser<S>, S: Stage>(PhantomData<(S, T)>);
impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
const PATH: &[Symbol] = T::PATH;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const TEMPLATE: AttributeTemplate = template!(Word);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
}
Some(T::CREATE(cx.attr_span))
}
}
type ConvertFn<E> = fn(ThinVec<E>) -> AttributeKind;
/// Alternative to [`AttributeParser`] that automatically handles state management.