|  | 
| 1 | 1 | //! Centralized logic for parsing and attributes. | 
| 2 | 2 | //! | 
| 3 |  | -//! Part of a series of crates: | 
| 4 |  | -//! - rustc_attr_data_structures: contains types that the parsers parse into | 
| 5 |  | -//! - rustc_attr_parsing: this crate | 
| 6 |  | -//! - (in the future): rustc_attr_validation | 
|  | 3 | +//! ## Architecture | 
|  | 4 | +//! This crate is part of a series of crates that handle attribute processing. | 
|  | 5 | +//! - [rustc_attr_data_structures](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_data_structures/index.html): Defines the data structures that store parsed attributes | 
|  | 6 | +//! - [rustc_attr_parsing](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html): This crate, handles the parsing of attributes | 
|  | 7 | +//! - (planned) rustc_attr_validation: Will handle attribute validation | 
| 7 | 8 | //! | 
| 8 |  | -//! History: Check out [#131229](https://github.com/rust-lang/rust/issues/131229). | 
| 9 |  | -//! There used to be only one definition of attributes in the compiler: `ast::Attribute`. | 
| 10 |  | -//! These were then parsed or validated or both in places distributed all over the compiler. | 
| 11 |  | -//! This was a mess... | 
|  | 9 | +//! The separation between data structures and parsing follows the principle of separation of concerns. | 
|  | 10 | +//! Data structures (`rustc_attr_data_structures`) define what attributes look like after parsing. | 
|  | 11 | +//! This crate (`rustc_attr_parsing`) handles how to convert raw tokens into those structures. | 
|  | 12 | +//! This split allows other parts of the compiler to use the data structures without needing | 
|  | 13 | +//! the parsing logic, making the codebase more modular and maintainable. | 
| 12 | 14 | //! | 
| 13 |  | -//! Attributes are markers on items. | 
| 14 |  | -//! Many of them are actually attribute-like proc-macros, and are expanded to some other rust syntax. | 
| 15 |  | -//! This could either be a user provided proc macro, or something compiler provided. | 
| 16 |  | -//! `derive` is an example of one that the compiler provides. | 
| 17 |  | -//! These are built-in, but they have a valid expansion to Rust tokens and are thus called "active". | 
| 18 |  | -//! I personally like calling these *active* compiler-provided attributes, built-in *macros*, | 
| 19 |  | -//! because they still expand, and this helps to differentiate them from built-in *attributes*. | 
| 20 |  | -//! However, I'll be the first to admit that the naming here can be confusing. | 
|  | 15 | +//! ## Background | 
|  | 16 | +//! Previously, the compiler had a single attribute definition (`ast::Attribute`) with parsing and | 
|  | 17 | +//! validation scattered throughout the codebase. This was reorganized for better maintainability | 
|  | 18 | +//! (see [#131229](https://github.com/rust-lang/rust/issues/131229)). | 
| 21 | 19 | //! | 
| 22 |  | -//! The alternative to active attributes, are inert attributes. | 
| 23 |  | -//! These can occur in user code (proc-macro helper attributes). | 
| 24 |  | -//! But what's important is, many built-in attributes are inert like this. | 
| 25 |  | -//! There is nothing they expand to during the macro expansion process, | 
| 26 |  | -//! sometimes because they literally cannot expand to something that is valid Rust. | 
| 27 |  | -//! They are really just markers to guide the compilation process. | 
| 28 |  | -//! An example is `#[inline(...)]` which changes how code for functions is generated. | 
|  | 20 | +//! ## Types of Attributes | 
|  | 21 | +//! In Rust, attributes are markers that can be attached to items. They come in two main categories. | 
|  | 22 | +//! | 
|  | 23 | +//! ### 1. Active Attributes | 
|  | 24 | +//! These are attribute-like proc-macros that expand into other Rust code. | 
|  | 25 | +//! They can be either user-defined or compiler-provided. Examples of compiler-provided active attributes: | 
|  | 26 | +//!   - `#[derive(...)]`: Expands into trait implementations | 
|  | 27 | +//!   - `#[cfg()]`: Expands based on configuration | 
|  | 28 | +//!   - `#[cfg_attr()]`: Conditional attribute application | 
|  | 29 | +//! | 
|  | 30 | +//! ### 2. Inert Attributes | 
|  | 31 | +//! These are pure markers that don't expand into other code. They guide the compilation process. | 
|  | 32 | +//! They can be user-defined (in proc-macro helpers) or built-in. Examples of built-in inert attributes: | 
|  | 33 | +//!   - `#[stable()]`: Marks stable API items | 
|  | 34 | +//!   - `#[inline()]`: Suggests function inlining | 
|  | 35 | +//!   - `#[repr()]`: Controls type representation | 
| 29 | 36 | //! | 
| 30 | 37 | //! ```text | 
| 31 | 38 | //!                      Active                 Inert | 
| 32 | 39 | //!              ┌──────────────────────┬──────────────────────┐ | 
| 33 | 40 | //!              │     (mostly in)      │    these are parsed  │ | 
| 34 | 41 | //!              │ rustc_builtin_macros │        here!         │ | 
| 35 | 42 | //!              │                      │                      │ | 
| 36 |  | -//!              │                      │                      │ | 
| 37 | 43 | //!              │    #[derive(...)]    │    #[stable()]       │ | 
| 38 | 44 | //!     Built-in │    #[cfg()]          │    #[inline()]       │ | 
| 39 | 45 | //!              │    #[cfg_attr()]     │    #[repr()]         │ | 
| 40 | 46 | //!              │                      │                      │ | 
| 41 |  | -//!              │                      │                      │ | 
| 42 |  | -//!              │                      │                      │ | 
| 43 | 47 | //!              ├──────────────────────┼──────────────────────┤ | 
| 44 | 48 | //!              │                      │                      │ | 
| 45 |  | -//!              │                      │                      │ | 
| 46 | 49 | //!              │                      │       `b` in         │ | 
| 47 | 50 | //!              │                      │ #[proc_macro_derive( │ | 
| 48 | 51 | //! User created │ #[proc_macro_attr()] │    a,                │ | 
| 49 | 52 | //!              │                      │    attributes(b)     │ | 
| 50 | 53 | //!              │                      │ ]                    │ | 
| 51 |  | -//!              │                      │                      │ | 
| 52 |  | -//!              │                      │                      │ | 
| 53 |  | -//!              │                      │                      │ | 
| 54 | 54 | //!              └──────────────────────┴──────────────────────┘ | 
| 55 | 55 | //! ``` | 
| 56 | 56 | //! | 
|  | 57 | +//! ## How This Crate Works | 
| 57 | 58 | //! In this crate, syntactical attributes (sequences of tokens that look like | 
| 58 | 59 | //! `#[something(something else)]`) are parsed into more semantic attributes, markers on items. | 
| 59 | 60 | //! Multiple syntactic attributes might influence a single semantic attribute. For example, | 
|  | 
| 63 | 64 | //! and `#[unstable()]` syntactic attributes, and at the end produce a single | 
| 64 | 65 | //! [`AttributeKind::Stability`](rustc_attr_data_structures::AttributeKind::Stability). | 
| 65 | 66 | //! | 
| 66 |  | -//! As a rule of thumb, when a syntactical attribute can be applied more than once, they should be | 
| 67 |  | -//! combined into a single semantic attribute. For example: | 
|  | 67 | +//! When multiple instances of the same attribute are allowed, they're combined into a single | 
|  | 68 | +//! semantic attribute. For example: | 
| 68 | 69 | //! | 
| 69 |  | -//! ``` | 
|  | 70 | +//! ```rust | 
| 70 | 71 | //! #[repr(C)] | 
| 71 | 72 | //! #[repr(packed)] | 
| 72 | 73 | //! struct Meow {} | 
| 73 | 74 | //! ``` | 
| 74 | 75 | //! | 
| 75 |  | -//! should result in a single `AttributeKind::Repr` containing a list of repr annotations, in this | 
| 76 |  | -//! case `C` and `packed`. This is equivalent to writing `#[repr(C, packed)]` in a single | 
| 77 |  | -//! syntactical annotation. | 
|  | 76 | +//! This is equivalent to `#[repr(C, packed)]` and results in a single `AttributeKind::Repr` | 
|  | 77 | +//! containing both `C` and `packed` annotations. | 
| 78 | 78 | 
 | 
| 79 | 79 | // tidy-alphabetical-start | 
| 80 | 80 | #![allow(internal_features)] | 
|  | 
0 commit comments