diff --git a/src/attributes.md b/src/attributes.md index bbd809f99..32d555c9e 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -1,44 +1,39 @@ # Attributes > **Syntax**\ -> _Attribute_ :\ ->    _InnerAttribute_ | _OuterAttribute_ -> > _InnerAttribute_ :\ ->    `#![` MetaItem `]` +>    `#` `!` `[` _Attr_ `]` > > _OuterAttribute_ :\ ->    `#[` MetaItem `]` -> -> _MetaItem_ :\ ->       [_SimplePath_]\ ->    | [_SimplePath_] `=` [_LiteralExpression_]_without suffix_\ ->    | [_SimplePath_] `(` _MetaSeq_? `)` +>    `#` `[` _Attr_ `]` > -> _MetaSeq_ :\ ->    _MetaItemInner_ ( `,` MetaItemInner )\* `,`? +> _Attr_ :\ +>    [_SimplePath_] _AttrInput_? > -> _MetaItemInner_ :\ ->       _MetaItem_\ ->    | [_LiteralExpression_]_without suffix_ +> _AttrInput_ :\ +>       [_DelimTokenTree_]\ +>    | `=` [_LiteralExpression_]_without suffix_ An _attribute_ is a general, free-form metadatum that is interpreted according to name, convention, and language and compiler version. Attributes are modeled on Attributes in [ECMA-335], with the syntax coming from [ECMA-334] \(C#). -Attributes may appear as any of: +_Inner attributes_, written with a bang (`!`) after the hash (`#`), apply to the +item that the attribute is declared within. _Outer attributes_, written without +the bang after the hash, apply to the thing that follows the attribute. -* A single identifier, the _attribute name_ -* An identifier followed by the equals sign '=' and a literal, providing a - key/value pair -* An identifier followed by a parenthesized list of sub-attribute arguments - which include literals +The attribute consists of a path to the attribute, followed by an optional +delimited token tree whose interpretation is defined by the attribute. +Attributes other than macro attributes also allow the input to be an equals +sign (`=`) followed by a literal expression. See the [meta item +syntax](#meta-item-attribute-syntax) below for more details. -Literal values must not include integer or float type suffixes. +Attributes can be classified into the following kinds: -_Inner attributes_, written with a bang ("!") after the hash ("#"), apply to the -item that the attribute is declared within. _Outer attributes_, written without -the bang after the hash, apply to the thing that follows the attribute. +* Built-in attributes +* [Macro attributes][attribute macro] +* [Derive macro helper attributes] +* [Tool attributes](#tool-attributes) Attributes may be applied to many things in the language: @@ -87,11 +82,34 @@ fn some_unused_variables() { } ``` -There are three kinds of attributes: +## Meta Item Attribute Syntax -* Built-in attributes -* Macro attributes -* Derive macro helper attributes +A "meta item" is the syntax used for the _Attr_ rule by most built-in +attributes and the [`meta` macro fragment specifier]. It has the following +grammar: + +> **Syntax**\ +> _MetaItem_ :\ +>       [_SimplePath_]\ +>    | [_SimplePath_] `=` [_LiteralExpression_]_without suffix_\ +>    | [_SimplePath_] `(` _MetaSeq_? `)` +> +> _MetaSeq_ :\ +>    _MetaItemInner_ ( `,` MetaItemInner )\* `,`? +> +> _MetaItemInner_ :\ +>       _MetaItem_\ +>    | [_LiteralExpression_]_without suffix_ + +Literal expressions in meta items must not include integer or float type +suffixes. + +Some examples of meta items are: +- `no_std` +- `doc = "example"` +- `cfg(any())` +- `deprecated(since = "1.2.0", note = "text")` +- `repr(align(32))` ## Active and inert attributes @@ -139,28 +157,18 @@ names have meaning. On an `extern` block, the following attributes are interpreted: -- `link_args` - specify arguments to the linker, rather than just the library - name and type. This is feature gated and the exact behavior is - implementation-defined (due to variety of linker invocation syntax). - `link` - indicate that a native library should be linked to for the declarations in this block to be linked correctly. `link` supports an optional `kind` key with three possible values: `dylib`, `static`, and `framework`. See [external blocks](items/external-blocks.html) for more about external blocks. Two examples: `#[link(name = "readline")]` and `#[link(name = "CoreFoundation", kind = "framework")]`. -- `linked_from` - indicates what native library this block of FFI items is - coming from. This attribute is of the form `#[linked_from = "foo"]` where - `foo` is the name of a library in either `#[link]` or a `-l` flag. This - attribute is currently required to export symbols from a Rust dynamic library - on Windows, and it is feature gated behind the `linked_from` feature. On declarations inside an `extern` block, the following attributes are interpreted: - `link_name` - the name of the symbol that this function or static should be imported as. -- `linkage` - on a static, this specifies the [linkage - type](http://llvm.org/docs/LangRef.html#linkage-types). See [type layout](type-layout.html) for documentation on the `repr` attribute which can be used to control type layout. @@ -175,8 +183,6 @@ which can be used to control type layout. macros named. The `extern crate` must appear at the crate root, not inside `mod`, which ensures proper function of the `$crate` macro variable. -- `macro_reexport` on an `extern crate` — re-export the named macros. - - `macro_export` - export a `macro_rules` macro for cross-crate usage. - `no_link` on an `extern crate` — even if we load this crate for macros, don't @@ -371,8 +377,7 @@ They only get checked when the associated tool is active, so if you try to use a Otherwise, they work just like regular lint attributes: - -```rust,ignore +```rust // set the entire `pedantic` clippy lint group to warn #![warn(clippy::pedantic)] // silence warnings from the `filter_map` clippy lint @@ -552,6 +557,34 @@ impl PartialEq for Foo { You can implement `derive` for your own traits through [procedural macros]. +## Tool attributes + +The compiler may allow attributes for external tools where each tool resides +in its own namespace. The first segment of the attribute path is the name of +the tool, with one or more additional segments whose interpretation is up to +the tool. + +When a tool is not in use, the tool's attributes are accepted without a +warning. When the tool is in use, the tool is responsible for processing and +interpretation of its attributes. + +Tool attributes are not available if the [`no_implicit_prelude`] attribute is +used. + +```rust +// Tells the rustfmt tool to not format the following element. +#[rustfmt::skip] +struct S { +} + +// Controls the "cyclomatic complexity" threshold for the clippy tool. +#[clippy::cyclomatic_complexity = "100"] +pub fn f() {} +``` + +> Note: `rustc` currently recognizes the tools "clippy" and "rustfmt". + +[_DelimTokenTree_]: macros.html [_LiteralExpression_]: expressions/literal-expr.html [_SimplePath_]: paths.html#simple-paths [`no_implicit_prelude`]: items/modules.html#prelude-items @@ -585,6 +618,7 @@ You can implement `derive` for your own traits through [procedural macros]. [external blocks]: items/external-blocks.html [items]: items.html [attribute macro]: procedural-macros.html#attribute-macros +[derive macro helper attributes]: procedural-macros.html#derive-macro-helper-attributes [function-like macro]: procedural-macros.html#function-like-procedural-macros [conditional compilation]: conditional-compilation.html [derive macro]: procedural-macros.html#derive-macros @@ -594,3 +628,4 @@ You can implement `derive` for your own traits through [procedural macros]. [where clause]: items/where-clauses.html [trait or lifetime bounds]: trait-bounds.html [Expression Attributes]: expressions.html#expression-attributes +[`meta` macro fragment specifier]: macros-by-example.html diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 8044db217..760f1d862 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -104,7 +104,7 @@ Example values: * `"android"` * `"freebsd"` * `"dragonfly"` -* `"bitrig"` +* `"bitrig"` * `"openbsd"` * `"netbsd"` @@ -151,7 +151,7 @@ Key-value option set once with the target's pointer width in bits. For example, for targets with 32-bit pointers, this is set to `"32"`. Likewise, it is set to `"64"` for targets with 64-bit pointers. - + ### `target_vendor` @@ -235,16 +235,16 @@ generic parameters. > **Syntax**\ > _CfgAttrAttribute_ :\ ->    `cfg_attr` `(` _ConfigurationPredicate_ `,` [_MetaItem_] `,`? `)` +>    `cfg_attr` `(` _ConfigurationPredicate_ `,` _CfgAttrs_? `)` +> +> _CfgAttrs_ :\ +>    [_Attr_] (`,` [_Attr_])\* `,`? The `cfg_attr` [attribute] conditionally includes [attributes] based on a configuration predicate. -It is written as `cfg_attr` followed by `(`, a configuration predicate, a -[metaitem], an optional `,`, and finally a `)`. - -When the configuration predicate is true, this attribute expands out to be an -attribute of the attribute metaitem. For example, the following module will +When the configuration predicate is true, this attribute expands out to the +attributes listed after the predicate. For example, the following module will either be found at `linux.rs` or `windows.rs` based on the target. ```rust,ignore @@ -253,6 +253,19 @@ either be found at `linux.rs` or `windows.rs` based on the target. mod os; ``` +Zero, one, or more attributes may be listed. Multiple attributes will each be +expanded into separate attributes. For example: + +```rust,ignore +#[cfg_attr(feature = "magic", sparkles, crackles)] +fn bewitched() {} + +// When the `magic` feature flag is enabled, the above will expand to: +#[sparkles] +#[crackles] +fn bewitched() {} +``` + > **Note**: The `cfg_attr` can expand to another `cfg_attr`. For example, > `#[cfg_attr(linux, cfg_attr(feature = "multithreaded", some_other_attribute))` > is valid. This example would be equivalent to @@ -284,7 +297,7 @@ println!("I'm running on a {} machine!", machine_kind); [IDENTIFIER]: identifiers.html [RAW_STRING_LITERAL]: tokens.html#raw-string-literals [STRING_LITERAL]: tokens.html#string-literals -[_MetaItem_]: attributes.html +[_Attr_]: attributes.html [`--cfg`]: ../rustc/command-line-arguments.html#a--cfg-configure-the-compilation-environment [`--test`]: ../rustc/command-line-arguments.html#a--test-build-a-test-harness [`cfg`]: #the-cfg-attribute @@ -296,4 +309,3 @@ println!("I'm running on a {} machine!", machine_kind); [crate type]: linkage.html [expressions]: expressions.html [items]: items.html -[metaitem]: attributes.html diff --git a/src/macros-by-example.md b/src/macros-by-example.md index c62e357c0..8156114a1 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -80,7 +80,7 @@ syntax named by _designator_. Valid designators are: [_Expression_]: expressions.html [_Item_]: items.html [_LiteralExpression_]: expressions/literal-expr.html -[_MetaItem_]: attributes.html +[_MetaItem_]: attributes.html#meta-item-attribute-syntax [_Pattern_]: patterns.html [_Statement_]: statements.html [_TokenTree_]: macros.html#macro-invocation diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 6875e908f..d788b7ad0 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -77,7 +77,7 @@ These macros are defined by a [public] [function] with the `proc_macro` [`TokenStream`] is what is inside the delimiters of the macro invocation and the output [`TokenStream`] replaces the entire macro invocation. It may contain an arbitrary number of [items]. These macros cannot expand to syntax that defines -new `macro_rule` style macros. +new `macro_rules` style macros. For example, the following macro definition ignores its input and outputs a function `answer` into its scope. @@ -195,14 +195,14 @@ struct Struct { *Attribute macros* define new [attributes] which can be attached to [items]. Attribute macros are defined by a [public] [function] with the -`proc_macro_attribute` [attribute] that a signature of -`(TokenStream, TokenStream) -> TokenStream`. The first [`TokenStream`] is the -attribute's metaitems, not including the delimiters. If the attribute is written -without a metaitem, the attribute [`TokenStream`] is empty. The second -[`TokenStream`] is of the rest of the [item] including other [attributes] on the -[item]. The returned [`TokenStream`] replaces the [item] with an arbitrary -number of [items]. These macros cannot expand to syntax that defines new -`macro_rule` style macros. +`proc_macro_attribute` [attribute] that has a signature of `(TokenStream, +TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token +tree following the attribute's name, not including the outer delimiters. If +the attribute is written as a bare attribute name, the attribute +[`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] +including other [attributes] on the [item]. The returned [`TokenStream`] +replaces the [item] with an arbitrary number of [items]. These macros cannot +expand to syntax that defines new `macro_rules` style macros. For example, this attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. @@ -247,16 +247,16 @@ fn invoke1() {} // out: attr: "" // out: item: "fn invoke1() { }" -// Example: Attribute has a metaitem +// Example: Attribute with input #[show_streams(bar)] fn invoke2() {} // out: attr: "bar" // out: item: "fn invoke2() {}" -// Example: Multiple words in metaitem -#[show_streams(multiple words)] +// Example: Multiple tokens in the input +#[show_streams(multiple => tokens)] fn invoke3() {} -// out: attr: "multiple words" +// out: attr: "multiple => tokens" // out: item: "fn invoke3() {}" // Example: diff --git a/src/type-layout.md b/src/type-layout.md index c746855fa..9d56851bd 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -116,7 +116,7 @@ The possible representations for a type are the default representation, `C`, the primitive representations, and `packed`. Multiple representations can be applied to a single type. -The representation of a type can be changed by applying the [`repr` attribute] +The representation of a type can be changed by applying the `repr` attribute to it. The following example shows a struct with a `C` representation. ``` @@ -332,4 +332,4 @@ used with any other representation. [zero-variant enumerations]: items/enumerations.html#zero-variant-enums [undefined behavior]: behavior-considered-undefined.html [27060]: https://github.com/rust-lang/rust/issues/27060 -[`PhantomData`]: special-types-and-traits.html#phantomdatat \ No newline at end of file +[`PhantomData`]: special-types-and-traits.html#phantomdatat