Skip to content

Simplify attribute_groups #140539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ use crate::session_diagnostics;

pub(crate) struct AllowInternalUnstableParser;
impl CombineAttributeParser for AllowInternalUnstableParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
const PATH: Symbol = sym::allow_internal_unstable;
type Item = (Symbol, Span);
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;

fn extend<'a>(
cx: &'a AcceptContext<'a>,
args: &'a ArgParser<'a>,
) -> impl IntoIterator<Item = Self::Item> + 'a {
parse_unstable(cx, args, Self::PATH[0]).into_iter().zip(iter::repeat(cx.attr_span))
parse_unstable(cx, args, Self::PATH).into_iter().zip(iter::repeat(cx.attr_span))
}
}

pub(crate) struct AllowConstFnUnstableParser;
impl CombineAttributeParser for AllowConstFnUnstableParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
const PATH: Symbol = sym::rustc_allow_const_fn_unstable;
type Item = Symbol;
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;

fn extend<'a>(
cx: &'a AcceptContext<'a>,
args: &'a ArgParser<'a>,
) -> impl IntoIterator<Item = Self::Item> + 'a {
parse_unstable(cx, args, Self::PATH[0])
parse_unstable(cx, args, Self::PATH)
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/confusables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) struct ConfusablesParser {
}

impl AttributeParser for ConfusablesParser {
const ATTRIBUTES: AcceptMapping<Self> = &[(&[sym::rustc_confusables], |this, cx, args| {
const ATTRIBUTES: AcceptMapping<Self> = &[(sym::rustc_confusables, |this, cx, args| {
let Some(list) = args.list() else {
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
// NOTE: currently subsequent attributes are silently ignored using
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ fn get(
}

impl SingleAttributeParser for DeprecationParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::deprecated];
const PATH: Symbol = sym::deprecated;

fn on_duplicate(cx: &AcceptContext<'_>, first_span: rustc_span::Span) {
fn on_duplicate(cx: &AcceptContext<'_>, first_span: Span) {
// FIXME(jdonszelmann): merge with errors from check_attrs.rs
cx.emit_err(session_diagnostics::UnusedMultiple {
this: cx.attr_span,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use std::marker::PhantomData;

use rustc_attr_data_structures::AttributeKind;
use rustc_span::Span;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;

use crate::context::{AcceptContext, FinalizeContext};
Expand All @@ -33,7 +33,7 @@ pub(crate) mod transparency;
pub(crate) mod util;

type AcceptFn<T> = fn(&mut T, &AcceptContext<'_>, &ArgParser<'_>);
type AcceptMapping<T> = &'static [(&'static [rustc_span::Symbol], AcceptFn<T>)];
type AcceptMapping<T> = &'static [(Symbol, AcceptFn<T>)];

/// An [`AttributeParser`] is a type which searches for syntactic attributes.
///
Expand Down Expand Up @@ -72,7 +72,7 @@ pub(crate) trait AttributeParser: Default + 'static {
/// [`SingleAttributeParser`] can only convert attributes one-to-one, and cannot combine multiple
/// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
pub(crate) trait SingleAttributeParser: 'static {
const PATH: &'static [rustc_span::Symbol];
const PATH: Symbol;

/// Caled when a duplicate attribute is found.
///
Expand Down Expand Up @@ -119,7 +119,7 @@ type ConvertFn<E> = fn(ThinVec<E>) -> AttributeKind;
/// [`CombineAttributeParser`] can only convert a single kind of attribute, and cannot combine multiple
/// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
pub(crate) trait CombineAttributeParser: 'static {
const PATH: &'static [rustc_span::Symbol];
const PATH: Symbol;

type Item;
const CONVERT: ConvertFn<Self::Item>;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) struct ReprParser;

impl CombineAttributeParser for ReprParser {
type Item = (ReprAttr, Span);
const PATH: &'static [rustc_span::Symbol] = &[sym::repr];
const PATH: Symbol = sym::repr;
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Repr;

fn extend<'a>(
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,23 @@ impl StabilityParser {

impl AttributeParser for StabilityParser {
const ATTRIBUTES: AcceptMapping<Self> = &[
(&[sym::stable], |this, cx, args| {
(sym::stable, |this, cx, args| {
reject_outside_std!(cx);
if !this.check_duplicate(cx)
&& let Some((feature, level)) = parse_stability(cx, args)
{
this.stability = Some((Stability { level, feature }, cx.attr_span));
}
}),
(&[sym::unstable], |this, cx, args| {
(sym::unstable, |this, cx, args| {
reject_outside_std!(cx);
if !this.check_duplicate(cx)
&& let Some((feature, level)) = parse_unstability(cx, args)
{
this.stability = Some((Stability { level, feature }, cx.attr_span));
}
}),
(&[sym::rustc_allowed_through_unstable_modules], |this, cx, args| {
(sym::rustc_allowed_through_unstable_modules, |this, cx, args| {
reject_outside_std!(cx);
this.allowed_through_unstable_modules = args.name_value().and_then(|i| i.value_as_str())
}),
Expand Down Expand Up @@ -97,7 +97,7 @@ pub(crate) struct BodyStabilityParser {

impl AttributeParser for BodyStabilityParser {
const ATTRIBUTES: AcceptMapping<Self> =
&[(&[sym::rustc_default_body_unstable], |this, cx, args| {
&[(sym::rustc_default_body_unstable, |this, cx, args| {
reject_outside_std!(cx);
if this.stability.is_some() {
cx.dcx()
Expand All @@ -117,7 +117,7 @@ impl AttributeParser for BodyStabilityParser {
pub(crate) struct ConstStabilityIndirectParser;
// FIXME(jdonszelmann): single word attribute group when we have these
impl SingleAttributeParser for ConstStabilityIndirectParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_const_stable_indirect];
const PATH: Symbol = sym::rustc_const_stable_indirect;

// ignore
fn on_duplicate(_cx: &AcceptContext<'_>, _first_span: Span) {}
Expand Down Expand Up @@ -147,7 +147,7 @@ impl ConstStabilityParser {

impl AttributeParser for ConstStabilityParser {
const ATTRIBUTES: AcceptMapping<Self> = &[
(&[sym::rustc_const_stable], |this, cx, args| {
(sym::rustc_const_stable, |this, cx, args| {
reject_outside_std!(cx);

if !this.check_duplicate(cx)
Expand All @@ -159,7 +159,7 @@ impl AttributeParser for ConstStabilityParser {
));
}
}),
(&[sym::rustc_const_unstable], |this, cx, args| {
(sym::rustc_const_unstable, |this, cx, args| {
reject_outside_std!(cx);
if !this.check_duplicate(cx)
&& let Some((feature, level)) = parse_unstability(cx, args)
Expand All @@ -170,7 +170,7 @@ impl AttributeParser for ConstStabilityParser {
));
}
}),
(&[sym::rustc_promotable], |this, cx, _| {
(sym::rustc_promotable, |this, cx, _| {
reject_outside_std!(cx);
this.promotable = true;
}),
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/transparency.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_span::hygiene::Transparency;
use rustc_span::sym;
use rustc_span::{Span, Symbol, sym};

use super::{AcceptContext, SingleAttributeParser};
use crate::parser::ArgParser;
Expand All @@ -11,9 +11,9 @@ pub(crate) struct TransparencyParser;
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
impl SingleAttributeParser for TransparencyParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_transparency];
const PATH: Symbol = sym::rustc_macro_transparency;

fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: rustc_span::Span) {
fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: Span) {
cx.dcx().span_err(vec![first_span, cx.attr_span], "multiple macro transparency attributes");
}

Expand Down
64 changes: 33 additions & 31 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,29 @@ macro_rules! attribute_groups {
(
pub(crate) static $name: ident = [$($names: ty),* $(,)?];
) => {
pub(crate) static $name: LazyLock<(
BTreeMap<&'static [Symbol], Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>,
Vec<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>
)> = LazyLock::new(|| {
let mut accepts = BTreeMap::<_, Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>::new();
let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>::new();
type Accepts = BTreeMap<
Symbol,
Box<dyn Send + Sync + Fn(&AcceptContext<'_>, &ArgParser<'_>)>
>;
type Finalizes = Vec<
Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>
>;
pub(crate) static $name: LazyLock<(Accepts, Finalizes)> = LazyLock::new(|| {
let mut accepts = Accepts::new();
let mut finalizes = Finalizes::new();
$(
{
thread_local! {
static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
};

for (k, v) in <$names>::ATTRIBUTES {
accepts.entry(*k).or_default().push(Box::new(|cx, args| {
let old = accepts.insert(*k, Box::new(|cx, args| {
STATE_OBJECT.with_borrow_mut(|s| {
v(s, cx, args)
})
}));
assert!(old.is_none());
}

finalizes.push(Box::new(|cx| {
Expand Down Expand Up @@ -110,7 +115,8 @@ impl<'a> Deref for AcceptContext<'a> {

/// Context given to every attribute parser during finalization.
///
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create errors, for example.
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
/// errors, for example.
pub(crate) struct FinalizeContext<'a> {
/// The parse context, gives access to the session and the
/// diagnostics context.
Expand Down Expand Up @@ -141,10 +147,9 @@ pub struct AttributeParser<'sess> {
sess: &'sess Session,
features: Option<&'sess Features>,

/// *only* parse attributes with this symbol.
/// *Only* parse attributes with this symbol.
///
/// Used in cases where we want the lowering infrastructure for
/// parse just a single attribute.
/// Used in cases where we want the lowering infrastructure for parse just a single attribute.
parse_only: Option<Symbol>,

/// Can be used to instruct parsers to reduce the number of diagnostics it emits.
Expand All @@ -157,9 +162,9 @@ impl<'sess> AttributeParser<'sess> {
/// One example where this is necessary, is to parse `feature` attributes themselves for
/// example.
///
/// Try to use this as little as possible. Attributes *should* be lowered during `rustc_ast_lowering`.
/// Some attributes require access to features to parse, which would crash if you tried to do so
/// through [`parse_limited`](Self::parse_limited).
/// Try to use this as little as possible. Attributes *should* be lowered during
/// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
/// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
///
/// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
/// that symbol are picked out of the list of instructions and parsed. Those are returned.
Expand Down Expand Up @@ -217,19 +222,18 @@ impl<'sess> AttributeParser<'sess> {
let group_cx = FinalizeContext { cx: self, target_span };

for attr in attrs {
// if we're only looking for a single attribute,
// skip all the ones we don't care about
// If we're only looking for a single attribute, skip all the ones we don't care about.
if let Some(expected) = self.parse_only {
if !attr.has_name(expected) {
continue;
}
}

// sometimes, for example for `#![doc = include_str!("readme.md")]`,
// Sometimes, for example for `#![doc = include_str!("readme.md")]`,
// doc still contains a non-literal. You might say, when we're lowering attributes
// that's expanded right? But no, sometimes, when parsing attributes on macros,
// we already use the lowering logic and these are still there. So, when `omit_doc`
// is set we *also* want to ignore these
// is set we *also* want to ignore these.
if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
continue;
}
Expand Down Expand Up @@ -263,21 +267,19 @@ impl<'sess> AttributeParser<'sess> {
let (path, args) = parser.deconstruct();
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();

if let Some(accepts) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
for f in accepts {
let cx = AcceptContext {
group_cx: &group_cx,
attr_span: lower_span(attr.span),
};
if let [part] = &parts[..]
&& let Some(accept) = ATTRIBUTE_MAPPING.0.get(part)
{
let cx =
AcceptContext { group_cx: &group_cx, attr_span: lower_span(attr.span) };

f(&cx, &args)
}
accept(&cx, &args)
} else {
// if we're here, we must be compiling a tool attribute... Or someone forgot to
// parse their fancy new attribute. Let's warn them in any case. If you are that
// person, and you really your attribute should remain unparsed, carefully read the
// documentation in this module and if you still think so you can add an exception
// to this assertion.
// If we're here, we must be compiling a tool attribute... Or someone
// forgot to parse their fancy new attribute. Let's warn them in any case.
// If you are that person, and you really think your attribute should
// remain unparsed, carefully read the documentation in this module and if
// you still think so you can add an exception to this assertion.

// FIXME(jdonszelmann): convert other attributes, and check with this that
// we caught em all
Expand Down
Loading