rustc_attr_parsing/
lib.rs

1//! Centralized logic for parsing and attributes.
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
7//!
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...
12//!
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.
21//!
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.
29//!
30//! ```text
31//!                      Active                 Inert
32//!              ┌──────────────────────┬──────────────────────┐
33//!              │     (mostly in)      │    these are parsed  │
34//!              │ rustc_builtin_macros │        here!         │
35//!              │                      │                      │
36//!              │                      │                      │
37//!              │    #[derive(...)]    │    #[stable()]       │
38//!     Built-in │    #[cfg()]          │    #[inline()]       │
39//!              │    #[cfg_attr()]     │    #[repr()]         │
40//!              │                      │                      │
41//!              │                      │                      │
42//!              │                      │                      │
43//!              ├──────────────────────┼──────────────────────┤
44//!              │                      │                      │
45//!              │                      │                      │
46//!              │                      │       `b` in         │
47//!              │                      │ #[proc_macro_derive( │
48//! User created │ #[proc_macro_attr()] │    a,                │
49//!              │                      │    attributes(b)     │
50//!              │                      │ ]                    │
51//!              │                      │                      │
52//!              │                      │                      │
53//!              │                      │                      │
54//!              └──────────────────────┴──────────────────────┘
55//! ```
56//!
57//! In this crate, syntactical attributes (sequences of tokens that look like
58//! `#[something(something else)]`) are parsed into more semantic attributes, markers on items.
59//! Multiple syntactic attributes might influence a single semantic attribute. For example,
60//! `#[stable(...)]` and `#[unstable()]` cannot occur together, and both semantically define
61//! a "stability" of an item. So, the stability attribute has an
62//! [`AttributeParser`](attributes::AttributeParser) that recognizes both the `#[stable()]`
63//! and `#[unstable()]` syntactic attributes, and at the end produce a single [`AttributeKind::Stability`].
64//!
65//! As a rule of thumb, when a syntactical attribute can be applied more than once, they should be
66//! combined into a single semantic attribute. For example:
67//!
68//! ```
69//! #[repr(C)]
70//! #[repr(packed)]
71//! struct Meow {}
72//! ```
73//!
74//! should result in a single `AttributeKind::Repr` containing a list of repr annotations, in this
75//! case `C` and `packed`. This is equivalent to writing `#[repr(C, packed)]` in a single
76//! syntactical annotation.
77
78// tidy-alphabetical-start
79#![allow(internal_features)]
80#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
81#![doc(rust_logo)]
82#![feature(let_chains)]
83#![feature(rustdoc_internals)]
84// tidy-alphabetical-end
85
86#[macro_use]
87mod attributes;
88mod context;
89pub mod parser;
90mod session_diagnostics;
91
92pub use attributes::cfg::*;
93pub use attributes::util::{find_crate_name, is_builtin_attr, parse_version};
94pub use context::{AttributeParser, OmitDoc};
95pub use rustc_attr_data_structures::*;
96
97rustc_fluent_macro::fluent_messages! { "../messages.ftl" }