Skip to content

Commit

Permalink
Merge pull request #528 from ehuss/attribute-update
Browse files Browse the repository at this point in the history
Update attribute documentation.
  • Loading branch information
Centril authored Mar 5, 2019
2 parents 456f735 + 609d740 commit ce592df
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 69 deletions.
121 changes: 78 additions & 43 deletions src/attributes.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,39 @@
# Attributes

> **<sup>Syntax</sup>**\
> _Attribute_ :\
> &nbsp;&nbsp; _InnerAttribute_ | _OuterAttribute_
>
> _InnerAttribute_ :\
> &nbsp;&nbsp; `#![` MetaItem `]`
> &nbsp;&nbsp; `#` `!` `[` _Attr_ `]`
>
> _OuterAttribute_ :\
> &nbsp;&nbsp; `#[` MetaItem `]`
>
> _MetaItem_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_SimplePath_]\
> &nbsp;&nbsp; | [_SimplePath_] `=` [_LiteralExpression_]<sub>_without suffix_</sub>\
> &nbsp;&nbsp; | [_SimplePath_] `(` _MetaSeq_<sup>?</sup> `)`
> &nbsp;&nbsp; `#` `[` _Attr_ `]`
>
> _MetaSeq_ :\
> &nbsp;&nbsp; _MetaItemInner_ ( `,` MetaItemInner )<sup>\*</sup> `,`<sup>?</sup>
> _Attr_ :\
> &nbsp;&nbsp; [_SimplePath_] _AttrInput_<sup>?</sup>
>
> _MetaItemInner_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _MetaItem_\
> &nbsp;&nbsp; | [_LiteralExpression_]<sub>_without suffix_</sub>
> _AttrInput_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_DelimTokenTree_]\
> &nbsp;&nbsp; | `=` [_LiteralExpression_]<sub>_without suffix_</sub>
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:

Expand Down Expand Up @@ -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:

> **<sup>Syntax</sup>**\
> _MetaItem_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_SimplePath_]\
> &nbsp;&nbsp; | [_SimplePath_] `=` [_LiteralExpression_]<sub>_without suffix_</sub>\
> &nbsp;&nbsp; | [_SimplePath_] `(` _MetaSeq_<sup>?</sup> `)`
>
> _MetaSeq_ :\
> &nbsp;&nbsp; _MetaItemInner_ ( `,` MetaItemInner )<sup>\*</sup> `,`<sup>?</sup>
>
> _MetaItemInner_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _MetaItem_\
> &nbsp;&nbsp; | [_LiteralExpression_]<sub>_without suffix_</sub>
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

Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -552,6 +557,34 @@ impl<T: PartialEq> PartialEq for Foo<T> {

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
Expand Down Expand Up @@ -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
Expand All @@ -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
32 changes: 22 additions & 10 deletions src/conditional-compilation.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Example values:
* `"android"`
* `"freebsd"`
* `"dragonfly"`
* `"bitrig"`
* `"bitrig"`
* `"openbsd"`
* `"netbsd"`

Expand Down Expand Up @@ -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.

<!-- Are there targets that have a different bit number? -->
<!-- Are there targets that have a different bit number? -->

### `target_vendor`

Expand Down Expand Up @@ -235,16 +235,16 @@ generic parameters.

> **<sup>Syntax</sup>**\
> _CfgAttrAttribute_ :\
> &nbsp;&nbsp; `cfg_attr` `(` _ConfigurationPredicate_ `,` [_MetaItem_] `,`<sup>?</sup> `)`
> &nbsp;&nbsp; `cfg_attr` `(` _ConfigurationPredicate_ `,` _CfgAttrs_<sup>?</sup> `)`
>
> _CfgAttrs_ :\
> &nbsp;&nbsp; [_Attr_]&nbsp;(`,` [_Attr_])<sup>\*</sup> `,`<sup>?</sup>
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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
2 changes: 1 addition & 1 deletion src/macros-by-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 13 additions & 13 deletions src/procedural-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ These macros are defined by a [public]&#32;[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.
Expand Down Expand Up @@ -195,14 +195,14 @@ struct Struct {
*Attribute macros* define new [attributes] which can be attached to [items].

Attribute macros are defined by a [public]&#32;[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.
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions src/type-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

```
Expand Down Expand Up @@ -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<T>`]: special-types-and-traits.html#phantomdatat
[`PhantomData<T>`]: special-types-and-traits.html#phantomdatat

0 comments on commit ce592df

Please sign in to comment.