Skip to content

New attribute parsing infrastructure #135726

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

Merged
merged 10 commits into from
Feb 25, 2025
29 changes: 21 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
mod allow_unstable;
mod cfg;
mod confusables;
mod deprecation;
mod repr;
mod stability;
mod transparency;
//! You can find more docs on what groups are on [`AttributeParser`] itself.
//! However, for many types of attributes, implementing [`AttributeParser`] is not necessary.
//! It allows for a lot of flexibility you might not want.
//!
//! Specifically, you might not care about managing the state of your [`AttributeParser`]
//! state machine yourself. In this case you can choose to implement:
//!
//! - [`SingleAttributeParser`]: makes it easy to implement an attribute which should error if it
//! appears more than once in a list of attributes
//! - [`CombineAttributeParser`]: makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
//! Attributes should be added to [`ATTRIBUTE_GROUP_MAPPING`](crate::context::ATTRIBUTE_GROUP_MAPPING) to be parsed.

pub mod util;
pub(crate) mod allow_unstable;
pub(crate) mod cfg;
pub(crate) mod confusables;
pub(crate) mod deprecation;
pub(crate) mod repr;
pub(crate) mod stability;
pub(crate) mod transparency;
pub(crate) mod util;

pub use allow_unstable::*;
pub use cfg::*;
Expand Down
41 changes: 37 additions & 4 deletions compiler/rustc_attr_parsing/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,41 @@
//! Functions and types dealing with attributes and meta items.
//! Centralized logic for parsing and attributes.
//!
//! FIXME(Centril): For now being, much of the logic is still in `rustc_ast::attr`.
//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
//! to this crate.
//! Part of a series of crates:
//! - rustc_attr_data_structures: contains types that the parsers parse into
//! - rustc_attr_parsing: this crate
//! - (in the future): rustc_attr_validation
//!
//! History: Check out [#131229](https://github.com/rust-lang/rust/issues/131229).
//! There used to be only one definition of attributes in the compiler: `ast::Attribute`.
//! These were then parsed or validated or both in places distributed all over the compiler.
//! This was a mess...
//!
//! Attributes are markers on items. Most are actually attribute-like proc-macros, and are expanded
//! but some remain as the so-called built-in attributes. These are not macros at all, and really
//! are just markers to guide the compilation process. An example is `#[inline(...)]` which changes
//! how code for functions is generated. Built-in attributes aren't macros because there's no rust
//! syntax they could expand to.
//!
//! In this crate, syntactical attributes (sequences of tokens that look like
//! `#[something(something else)]`) are parsed into more semantic attributes, markers on items.
//! Multiple syntactic attributes might influence a single semantic attribute. For example,
//! `#[stable(...)]` and `#[unstable()]` cannot occur together, and both semantically define
//! a "stability" of an item. So, the stability attribute has an
//! [`AttributeParser`](attributes::AttributeParser) that recognizes both the `#[stable()]`
//! and `#[unstable()]` syntactic attributes, and at the end produce a single [`AttributeKind::Stability`].
//!
//! As a rule of thumb, when a syntactical attribute can be applied more than once, they should be
//! combined into a single semantic attribute. For example:
//!
//! ```
//! #[repr(C)]
//! #[repr(packed)]
//! struct Meow {}
//! ```
//!
//! should result in a single `AttributeKind::Repr` containing a list of repr annotations, in this
//! case `C` and `packed`. This is equivalent to writing `#[repr(C, packed)]` in a single
//! syntactical annotation.

// tidy-alphabetical-start
#![allow(internal_features)]
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_codegen_ssa/src/assert_module_sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ impl<'tcx> AssertModuleSource<'tcx> {
other => {
self.tcx
.dcx()
.emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other });
.emit_fatal(errors::UnknownReuseKind { span: attr.span(), kind: other });
}
}
} else {
return;
};

if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span });
self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span() });
}

if !self.check_config(attr) {
Expand All @@ -115,7 +115,7 @@ impl<'tcx> AssertModuleSource<'tcx> {

if !user_path.starts_with(&crate_name) {
self.tcx.dcx().emit_fatal(errors::MalformedCguName {
span: attr.span,
span: attr.span(),
user_path,
crate_name,
});
Expand Down Expand Up @@ -145,7 +145,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
let cgu_names: Vec<&str> =
self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord();
self.tcx.dcx().emit_err(errors::NoModuleNamed {
span: attr.span,
span: attr.span(),
user_path,
cgu_name,
cgu_names: cgu_names.join(", "),
Expand All @@ -155,7 +155,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
self.cgu_reuse_tracker.set_expectation(
cgu_name,
user_path,
attr.span,
attr.span(),
expected_reuse,
comp_kind,
);
Expand All @@ -175,7 +175,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
}
}

self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span, name });
self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span(), name });
}

/// Scan for a `cfg="foo"` attribute and check whether we have a
Expand Down
Loading