Crate rustc_attr_parsing

Source
Expand description

Centralized logic for parsing and attributes.

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. 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. Many of them are actually attribute-like proc-macros, and are expanded to some other rust syntax. This could either be a user provided proc macro, or something compiler provided. derive is an example of one that the compiler provides. These are built-in, but they have a valid expansion to Rust tokens and are thus called “active”. I personally like calling these active compiler-provided attributes, built-in macros, because they still expand, and this helps to differentiate them from built-in attributes. However, I’ll be the first to admit that the naming here can be confusing.

The alternative to active attributes, are inert attributes. These can occur in user code (proc-macro helper attributes). But what’s important is, many built-in attributes are inert like this. There is nothing they expand to during the macro expansion process, sometimes because they literally cannot expand to something that is valid Rust. They are really just markers to guide the compilation process. An example is #[inline(...)] which changes how code for functions is generated.

                     Active                 Inert
             ┌──────────────────────┬──────────────────────┐
             │     (mostly in)      │    these are parsed  │
             │ rustc_builtin_macros │        here!         │
             │                      │                      │
             │                      │                      │
             │    #[derive(...)]    │    #[stable()]       │
    Built-in │    #[cfg()]          │    #[inline()]       │
             │    #[cfg_attr()]     │    #[repr()]         │
             │                      │                      │
             │                      │                      │
             │                      │                      │
             ├──────────────────────┼──────────────────────┤
             │                      │                      │
             │                      │                      │
             │                      │       `b` in         │
             │                      │ #[proc_macro_derive( │
User created │ #[proc_macro_attr()] │    a,                │
             │                      │    attributes(b)     │
             │                      │ ]                    │
             │                      │                      │
             │                      │                      │
             │                      │                      │
             └──────────────────────┴──────────────────────┘

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 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.

Modules§

attributes 🔒
This module defines traits for attribute parsers, little state machines that recognize and parse attributes out of a longer list of attributes. The main trait is called AttributeParser. You can find more docs about AttributeParsers on the trait itself. However, for many types of attributes, implementing AttributeParser is not necessary. It allows for a lot of flexibility you might not want.
context 🔒
parser
This is in essence an (improved) duplicate of rustc_ast/attr/mod.rs. That module is intended to be deleted in its entirety.
session_diagnostics 🔒

Structs§

AttributeParser
Context created once, for example as part of the ast lowering context, through which all attributes can be lowered.
Condition

Enums§

OmitDoc

Statics§

DEFAULT_LOCALE_RESOURCE
Raw content of Fluent resource for this crate, generated by fluent_messages macro, imported by rustc_driver to include all crates’ resources in one bundle.

Traits§

CfgMatchesLintEmitter
Emitter of a builtin lint from cfg_matches.

Functions§

cfg_matches
Tests if a cfg-pattern matches the cfg set
eval_condition
Evaluate a cfg-like condition (with any and all), using eval to evaluate individual items.
find_crate_name
is_builtin_attr
is_doc_alias_attrs_contain_symbol
parse_version
Parse a rustc version number written inside string literal in an attribute, like appears in since = "1.0.0". Suffixes like “-dev” and “-nightly” are not accepted in this position, unlike when parsing CFG_RELEASE.