Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3413,6 +3413,29 @@ pub struct Attribute {
/// Denotes if the attribute decorates the following construct (outer)
/// or the construct this attribute is contained within (inner).
pub style: AttrStyle,

/// The carets in the examples below show the spans for various cases.
/// ```text
/// #[foo] - A vanilla parsed attribute.
/// ^^^^^^ - Its span covers it all.
///
/// /** abc */ /// xyz - A parsed doc comment.
/// ^^^^^^^^^^ ^^^^^^^ - Its span covers the text and comment marker(s).
/// - The same span is also used if the doc comment is desugared (into
/// a new normal `#[doc = r"..."]` attribute) by
/// `desugar_doc_comments` before being passed to a macro (which
/// is done so that `#[$m:meta]` will match).
///
/// #[cfg_attr(pred, foo)] - A parsed `cfg_attr` attribute.
/// ^^^^^^^^^^^^^^^^^^^^^^ - Its span covers it all.
/// ^^^ - Span of the new replacement attribute (equivalent to `#[foo]`)
/// created by `cfg_attr` expansion (if `pred` is true).
/// ^^^^^^^^^^^^^^^^^^^^^^ - Span of the synthetic `CfgAttrTrace` attribute created by
/// `cfg_attr` expansion. (`CfgTrace` is derived from `#[cfg(..)]` and
/// handled similarly.)
/// ```
/// Finally, for compiler-generated attributes the span is whatever the construction site
/// chooses. Usually `DUMMY_SP` or some relevant span from the source code.
pub span: Span,
}

Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ use crate::mbe::macro_rules::ParserAnyMacro;
use crate::module::DirOwnership;
use crate::stats::MacroStat;

// When adding new variants, make sure to
// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector`
// to use `assign_id!`
/// This type encapsulates every AST node that can have attributes, i.e. those
/// nodes with a non-trivial implementation of `HasAttrs`.
///
/// When adding new variants, make sure to adjust the `visit_*` / `flat_map_*`
/// calls in `InvocationCollector` to use `assign_id!`
#[derive(Debug, Clone)]
pub enum Annotatable {
Item(Box<ast::Item>),
Expand Down Expand Up @@ -117,6 +119,7 @@ impl Annotatable {
}
}

/// Converts the `Annotatable` to a token stream, e.g. to hand to a proc macro.
pub fn to_tokens(&self) -> TokenStream {
match self {
Annotatable::Item(node) => TokenStream::from_ast(node),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_expand/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,14 +450,14 @@ pub(crate) struct GlobDelegationOutsideImpls {
}

#[derive(Diagnostic)]
#[diag("`crate_name` within an `#![cfg_attr]` attribute is forbidden")]
#[diag("`crate_name` within a `#![cfg_attr]` attribute is forbidden")]
pub(crate) struct CrateNameInCfgAttr {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("`crate_type` within an `#![cfg_attr]` attribute is forbidden")]
#[diag("`crate_type` within a `#![cfg_attr]` attribute is forbidden")]
pub(crate) struct CrateTypeInCfgAttr {
#[primary_span]
pub span: Span,
Expand Down
26 changes: 21 additions & 5 deletions compiler/rustc_parse/src/parser/attr_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,27 @@ impl<'a> Parser<'a> {

/// Parses code with `f`. If appropriate, it records the tokens (in
/// `LazyAttrTokenStream` form) that were parsed in the result, accessible
/// via the `HasTokens` trait. The `Trailing` part of the callback's
/// result indicates if an extra token should be captured, e.g. a comma or
/// semicolon. The `UsePreAttrPos` part of the callback's result indicates
/// if we should use `pre_attr_pos` as the collection start position (only
/// required in a few cases).
/// via the `HasTokens` trait.
///
/// Why is this done? Various macro cases require an AST node's tokens.
/// - Proc macros: all proc macros take a token stream.
/// - Function-style proc macros (`foo!(..)`): these can receive a token
/// stream without any parsing occurring within the parentheses.
/// - Attribute macros (`#[foo]`): at parse time (pre-resolution) we
/// don't know if a non-builtin `#[foo]` is an attribute proc macro, so
/// the parser does a full parse and collects tokens (lazily) in case.
/// - Derive macros (`derive(Foo)`): any input with
/// `#[cfg]`/`#[cfg_attr]` must be stripped before being passed to the
/// derive macro, which requires parsing. Identifying the end of the
/// item also requires parsing.
/// - Decl macros: a matched nonterminal (e.g. `$e:expr`) needs tokens in
/// case it is passed into a proc macro.
///
/// The `Trailing` part of the callback's result indicates if an extra
/// token should be captured, e.g. a comma or semicolon. The
/// `UsePreAttrPos` part of the callback's result indicates if we should
/// use `pre_attr_pos` as the collection start position (only required in a
/// few cases).
///
/// The `attrs` passed in are in `AttrWrapper` form, which is opaque. The
/// `AttrVec` within is passed to `f`. See the comment on `AttrWrapper` for
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/cfg/crate-attributes-using-cfg_attr.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
error: `crate_type` within an `#![cfg_attr]` attribute is forbidden
error: `crate_type` within a `#![cfg_attr]` attribute is forbidden
--> $DIR/crate-attributes-using-cfg_attr.rs:5:18
|
LL | #![cfg_attr(foo, crate_type="bin")]
| ^^^^^^^^^^^^^^^^

error: `crate_name` within an `#![cfg_attr]` attribute is forbidden
error: `crate_name` within a `#![cfg_attr]` attribute is forbidden
--> $DIR/crate-attributes-using-cfg_attr.rs:8:18
|
LL | #![cfg_attr(foo, crate_name="bar")]
| ^^^^^^^^^^^^^^^^

error: `crate_type` within an `#![cfg_attr]` attribute is forbidden
error: `crate_type` within a `#![cfg_attr]` attribute is forbidden
--> $DIR/crate-attributes-using-cfg_attr.rs:5:18
|
LL | #![cfg_attr(foo, crate_type="bin")]
| ^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: `crate_name` within an `#![cfg_attr]` attribute is forbidden
error: `crate_name` within a `#![cfg_attr]` attribute is forbidden
--> $DIR/crate-attributes-using-cfg_attr.rs:8:18
|
LL | #![cfg_attr(foo, crate_name="bar")]
Expand Down
Loading