From dbdbd30bf2cb0d48c8bbce83c2458592664dbb18 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Nov 2020 14:47:14 +0300 Subject: [PATCH 1/3] expand/resolve: Turn `#[derive]` into a regular macro attribute --- Cargo.lock | 1 + compiler/rustc_builtin_macros/Cargo.toml | 1 + compiler/rustc_builtin_macros/src/derive.rs | 132 ++++ compiler/rustc_builtin_macros/src/lib.rs | 2 + compiler/rustc_expand/src/base.rs | 44 +- compiler/rustc_expand/src/expand.rs | 339 +++----- compiler/rustc_expand/src/proc_macro.rs | 94 +-- compiler/rustc_feature/src/builtin_attrs.rs | 1 - compiler/rustc_lint/src/context.rs | 3 + compiler/rustc_lint_defs/src/builtin.rs | 50 +- compiler/rustc_lint_defs/src/lib.rs | 1 + compiler/rustc_parse/src/parser/attr.rs | 6 +- compiler/rustc_resolve/src/lib.rs | 3 + compiler/rustc_resolve/src/macros.rs | 145 ++-- library/core/src/macros/mod.rs | 8 + library/core/src/prelude/v1.rs | 5 + library/std/src/prelude/v1.rs | 5 + src/rustdoc-json-types/lib.rs | 30 +- src/test/run-make-fulldeps/simd-ffi/simd.rs | 5 + src/test/ui/derives/derive-deadlock.rs | 6 + src/test/ui/derives/derive-deadlock.stderr | 10 + .../ui/derives/derive-multiple-with-packed.rs | 10 + .../derives/deriving-meta-empty-trait-list.rs | 4 +- .../deriving-meta-empty-trait-list.stderr | 15 - src/test/ui/derives/issue-36617.rs | 3 +- src/test/ui/derives/issue-36617.stderr | 15 +- .../issue-43106-gating-of-derive.rs | 1 + .../issue-43106-gating-of-derive.stderr | 22 +- src/test/ui/issues/issue-49934-errors.rs | 9 +- src/test/ui/issues/issue-49934-errors.stderr | 13 +- src/test/ui/issues/issue-49934.rs | 17 +- src/test/ui/issues/issue-49934.stderr | 31 +- .../ui/macros/builtin-std-paths-fail.stderr | 44 +- .../issue-69341-malformed-derive-inert.rs | 5 +- .../issue-69341-malformed-derive-inert.stderr | 21 +- .../malformed/malformed-derive-entry.stderr | 2 +- .../malformed/malformed-special-attrs.stderr | 4 +- .../ui/proc-macro/attribute-after-derive.rs | 28 + .../proc-macro/attribute-after-derive.stdout | 148 ++++ .../proc-macro/attribute-order-restricted.rs | 14 - .../attribute-order-restricted.stderr | 8 - .../ui/proc-macro/derive-helper-shadowing.rs | 2 + .../proc-macro/derive-helper-shadowing.stderr | 27 +- .../ui/proc-macro/derive-helper-vs-legacy.rs | 12 + .../proc-macro/derive-multiple-with-packed.rs | 11 + .../helper-attr-blocked-by-import-ambig.rs | 4 +- ...helper-attr-blocked-by-import-ambig.stderr | 19 +- .../ui/proc-macro/issue-75930-derive-cfg.rs | 3 +- .../proc-macro/issue-75930-derive-cfg.stderr | 15 + .../proc-macro/issue-75930-derive-cfg.stdout | 728 +++++++++--------- .../ui/proc-macro/proc-macro-attributes.rs | 8 + .../proc-macro/proc-macro-attributes.stderr | 67 +- .../ui/proc-macro/reserved-macro-names.rs | 6 - .../ui/proc-macro/reserved-macro-names.stderr | 8 +- .../ui/span/issue-43927-non-ADT-derive.rs | 7 +- .../ui/span/issue-43927-non-ADT-derive.stderr | 31 +- src/test/ui/span/macro-ty-params.rs | 2 +- src/test/ui/span/macro-ty-params.stderr | 2 +- 58 files changed, 1249 insertions(+), 1008 deletions(-) create mode 100644 compiler/rustc_builtin_macros/src/derive.rs create mode 100644 src/test/ui/derives/derive-deadlock.rs create mode 100644 src/test/ui/derives/derive-deadlock.stderr create mode 100644 src/test/ui/derives/derive-multiple-with-packed.rs delete mode 100644 src/test/ui/derives/deriving-meta-empty-trait-list.stderr create mode 100644 src/test/ui/proc-macro/attribute-after-derive.rs create mode 100644 src/test/ui/proc-macro/attribute-after-derive.stdout delete mode 100644 src/test/ui/proc-macro/attribute-order-restricted.rs delete mode 100644 src/test/ui/proc-macro/attribute-order-restricted.stderr create mode 100644 src/test/ui/proc-macro/derive-helper-vs-legacy.rs create mode 100644 src/test/ui/proc-macro/derive-multiple-with-packed.rs create mode 100644 src/test/ui/proc-macro/issue-75930-derive-cfg.stderr diff --git a/Cargo.lock b/Cargo.lock index 9cabdb3edf698..6f29120455e55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3582,6 +3582,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_lexer", "rustc_parse", "rustc_parse_format", "rustc_session", diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index c397a85412627..eb022b5b2b16e 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -15,6 +15,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_lexer = { path = "../rustc_lexer" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs new file mode 100644 index 0000000000000..fad64858ce3ff --- /dev/null +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -0,0 +1,132 @@ +use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_errors::{struct_span_err, Applicability}; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; +use rustc_expand::config::StripUnconfigured; +use rustc_feature::AttributeTemplate; +use rustc_parse::validate_attr; +use rustc_session::Session; +use rustc_span::symbol::sym; +use rustc_span::Span; + +crate struct Expander; + +impl MultiItemModifier for Expander { + fn expand( + &self, + ecx: &mut ExtCtxt<'_>, + span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> ExpandResult, Annotatable> { + let sess = ecx.sess; + if report_bad_target(sess, &item, span) { + // We don't want to pass inappropriate targets to derive macros to avoid + // follow up errors, all other errors below are recoverable. + return ExpandResult::Ready(vec![item]); + } + + let template = + AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; + let attr = ecx.attribute(meta_item.clone()); + validate_attr::check_builtin_attribute(&sess.parse_sess, &attr, sym::derive, template); + + let derives: Vec<_> = attr + .meta_item_list() + .unwrap_or_default() + .into_iter() + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(meta) => Some(meta), + NestedMetaItem::Literal(lit) => { + // Reject `#[derive("Debug")]`. + report_unexpected_literal(sess, &lit); + None + } + }) + .map(|meta| { + // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. + report_path_args(sess, &meta); + meta.path + }) + .collect(); + + // FIXME: Try to cache intermediate results to avoid collecting same paths multiple times. + match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) { + Ok(()) => { + let mut visitor = + StripUnconfigured { sess, features: ecx.ecfg.features, modified: false }; + let mut item = visitor.fully_configure(item); + if visitor.modified { + // Erase the tokens if cfg-stripping modified the item + // This will cause us to synthesize fake tokens + // when `nt_to_tokenstream` is called on this item. + match &mut item { + Annotatable::Item(item) => item, + Annotatable::Stmt(stmt) => match &mut stmt.kind { + StmtKind::Item(item) => item, + _ => unreachable!(), + }, + _ => unreachable!(), + } + .tokens = None; + } + ExpandResult::Ready(vec![item]) + } + Err(Indeterminate) => ExpandResult::Retry(item), + } + } +} + +fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { + let item_kind = match item { + Annotatable::Item(item) => Some(&item.kind), + Annotatable::Stmt(stmt) => match &stmt.kind { + StmtKind::Item(item) => Some(&item.kind), + _ => None, + }, + _ => None, + }; + + let bad_target = + !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..))); + if bad_target { + struct_span_err!( + sess, + span, + E0774, + "`derive` may only be applied to structs, enums and unions", + ) + .emit(); + } + bad_target +} + +fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { + let help_msg = match lit.token.kind { + token::Str if rustc_lexer::is_ident(&lit.token.symbol.as_str()) => { + format!("try using `#[derive({})]`", lit.token.symbol) + } + _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), + }; + struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",) + .help(&help_msg) + .emit(); +} + +fn report_path_args(sess: &Session, meta: &ast::MetaItem) { + let report_error = |title, action| { + let span = meta.span.with_lo(meta.path.span.hi()); + sess.struct_span_err(span, title) + .span_suggestion(span, action, String::new(), Applicability::MachineApplicable) + .emit(); + }; + match meta.kind { + MetaItemKind::Word => {} + MetaItemKind::List(..) => report_error( + "traits in `#[derive(...)]` don't accept arguments", + "remove the arguments", + ), + MetaItemKind::NameValue(..) => { + report_error("traits in `#[derive(...)]` don't accept values", "remove the value") + } + } +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 59844b6c692ea..9a3c914337ca2 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -27,6 +27,7 @@ mod cfg_accessible; mod compile_error; mod concat; mod concat_idents; +mod derive; mod deriving; mod env; mod format; @@ -88,6 +89,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, + derive: derive::Expander, global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 08543d1622a7d..35ddb1fb9bc51 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -141,7 +141,7 @@ impl Annotatable { } crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { - nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No) + nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::Yes) } pub fn expect_item(self) -> P { @@ -234,25 +234,6 @@ impl Annotatable { _ => panic!("expected variant"), } } - - pub fn derive_allowed(&self) -> bool { - match *self { - Annotatable::Stmt(ref stmt) => match stmt.kind { - ast::StmtKind::Item(ref item) => matches!( - item.kind, - ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) - ), - _ => false, - }, - Annotatable::Item(ref item) => match item.kind { - ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => { - true - } - _ => false, - }, - _ => false, - } - } } /// Result of an expansion that may need to be retried. @@ -854,12 +835,6 @@ impl SyntaxExtension { } } -/// Result of resolving a macro invocation. -pub enum InvocationRes { - Single(Lrc), - DeriveContainer(Vec>), -} - /// Error type that denotes indeterminacy. pub struct Indeterminate; @@ -885,16 +860,29 @@ pub trait ResolverExpand { invoc: &Invocation, eager_expansion_root: ExpnId, force: bool, - ) -> Result; + ) -> Result, Indeterminate>; fn check_unused_macros(&mut self); /// Some parent node that is close enough to the given macro call. - fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId; + fn lint_node_id(&self, expn_id: ExpnId) -> NodeId; // Resolver interfaces for specific built-in macros. /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it? fn has_derive_copy(&self, expn_id: ExpnId) -> bool; + /// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`. + fn resolve_derives( + &mut self, + expn_id: ExpnId, + derives: Vec, + force: bool, + ) -> Result<(), Indeterminate>; + /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId` + /// back from resolver. + fn take_derive_resolutions( + &mut self, + expn_id: ExpnId, + ) -> Option, ast::Path)>>; /// Path resolution logic for `#[cfg_accessible(path)]`. fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5fdb7fc591594..870b5c92d8983 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,24 +1,26 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::configure; -use crate::hygiene::{ExpnData, ExpnKind, SyntaxContext}; +use crate::hygiene::SyntaxContext; use crate::mbe::macro_rules::annotate_err_with_kind; use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; use crate::placeholders::{placeholder, PlaceholderExpander}; -use crate::proc_macro::collect_derives; +use rustc_ast as ast; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{self as ast, AttrItem, AttrStyle, Block, LitKind, NodeId, PatKind, Path}; -use rustc_ast::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind, Unsafe}; +use rustc_ast::{AttrItem, AttrStyle, Block, ItemKind, LitKind, MacArgs}; +use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, NestedMetaItem}; +use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{struct_span_err, Applicability, PResult}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::{Applicability, PResult}; use rustc_feature::Features; use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser}; use rustc_parse::validate_attr; @@ -302,20 +304,11 @@ pub enum InvocationKind { item: Annotatable, // Required for resolving derive helper attributes. derives: Vec, - // We temporarily report errors for attribute macros placed after derives - after_derive: bool, }, Derive { path: Path, item: Annotatable, }, - /// "Invocation" that contains all derives from an item, - /// broken into multiple `Derive` invocations when expanded. - /// FIXME: Find a way to remove it. - DeriveContainer { - derives: Vec, - item: Annotatable, - }, } impl InvocationKind { @@ -328,7 +321,6 @@ impl InvocationKind { match self { InvocationKind::Attr { item: Annotatable::StructField(field), .. } | InvocationKind::Derive { item: Annotatable::StructField(field), .. } - | InvocationKind::DeriveContainer { item: Annotatable::StructField(field), .. } if field.ident.is_none() => { Some(field.vis.clone()) @@ -344,7 +336,6 @@ impl Invocation { InvocationKind::Bang { span, .. } => *span, InvocationKind::Attr { attr, .. } => attr.span, InvocationKind::Derive { path, .. } => path.span, - InvocationKind::DeriveContainer { item, .. } => item.span(), } } } @@ -446,7 +437,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let (invoc, res) = if let Some(invoc) = invocations.pop() { + let (invoc, ext) = if let Some(invoc) = invocations.pop() { invoc } else { self.resolve_imports(); @@ -464,8 +455,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue; }; - let res = match res { - Some(res) => res, + let ext = match ext { + Some(ext) => ext, None => { let eager_expansion_root = if self.monotonic { invoc.expansion_data.id @@ -477,7 +468,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { eager_expansion_root, force, ) { - Ok(res) => res, + Ok(ext) => ext, Err(Indeterminate) => { // Cannot resolve, will retry this invocation later. undetermined_invocations.push((invoc, None)); @@ -491,86 +482,78 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.current_expansion = invoc.expansion_data.clone(); self.cx.force_mode = force; - // FIXME(jseyfried): Refactor out the following logic let fragment_kind = invoc.fragment_kind; - let (expanded_fragment, new_invocations) = match res { - InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) { - ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]), - ExpandResult::Retry(invoc) => { - if force { - self.cx.span_bug( - invoc.span(), - "expansion entered force mode but is still stuck", - ); - } else { - // Cannot expand, will retry this invocation later. - undetermined_invocations - .push((invoc, Some(InvocationRes::Single(ext)))); - continue; - } - } - }, - InvocationRes::DeriveContainer(_exts) => { - // FIXME: Consider using the derive resolutions (`_exts`) immediately, - // instead of enqueuing the derives to be resolved again later. - let (derives, mut item) = match invoc.kind { - InvocationKind::DeriveContainer { derives, item } => (derives, item), - _ => unreachable!(), - }; - let (item, derive_placeholders) = if !item.derive_allowed() { - self.error_derive_forbidden_on_non_adt(&derives, &item); - item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive))); - (item, Vec::new()) - } else { - let mut visitor = StripUnconfigured { - sess: self.cx.sess, - features: self.cx.ecfg.features, - modified: false, - }; - let mut item = visitor.fully_configure(item); - item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive))); - if visitor.modified && !derives.is_empty() { - // Erase the tokens if cfg-stripping modified the item - // This will cause us to synthesize fake tokens - // when `nt_to_tokenstream` is called on this item. - match &mut item { - Annotatable::Item(item) => item.tokens = None, - Annotatable::Stmt(stmt) => { - if let StmtKind::Item(item) = &mut stmt.kind { - item.tokens = None - } else { - panic!("Unexpected stmt {:?}", stmt); - } - } - _ => panic!("Unexpected annotatable {:?}", item), + let (expanded_fragment, new_invocations) = match self.expand_invoc(invoc, &ext.kind) { + ExpandResult::Ready(fragment) => { + let derive_placeholders = self + .cx + .resolver + .take_derive_resolutions(expn_id) + .map(|derives| { + enum AnnotatableRef<'a> { + Item(&'a P), + Stmt(&'a ast::Stmt), } - } + let item = match &fragment { + AstFragment::Items(items) => match &items[..] { + [item] => AnnotatableRef::Item(item), + _ => unreachable!(), + }, + AstFragment::Stmts(stmts) => match &stmts[..] { + [stmt] => AnnotatableRef::Stmt(stmt), + _ => unreachable!(), + }, + _ => unreachable!(), + }; - invocations.reserve(derives.len()); - let derive_placeholders = derives - .into_iter() - .map(|path| { - let expn_id = ExpnId::fresh(None); - invocations.push(( - Invocation { - kind: InvocationKind::Derive { path, item: item.clone() }, - fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - ..self.cx.current_expansion.clone() + invocations.reserve(derives.len()); + derives + .into_iter() + .map(|(_exts, path)| { + // FIXME: Consider using the derive resolutions (`_exts`) + // instead of enqueuing the derives to be resolved again later. + let expn_id = ExpnId::fresh(None); + invocations.push(( + Invocation { + kind: InvocationKind::Derive { + path, + item: match item { + AnnotatableRef::Item(item) => { + Annotatable::Item(item.clone()) + } + AnnotatableRef::Stmt(stmt) => { + Annotatable::Stmt(P(stmt.clone())) + } + }, + }, + fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + ..self.cx.current_expansion.clone() + }, }, - }, - None, - )); - NodeId::placeholder_from_expn_id(expn_id) - }) - .collect::>(); - (item, derive_placeholders) - }; + None, + )); + NodeId::placeholder_from_expn_id(expn_id) + }) + .collect::>() + }) + .unwrap_or_default(); - let fragment = fragment_kind.expect_from_annotatables(::std::iter::once(item)); self.collect_invocations(fragment, &derive_placeholders) } + ExpandResult::Retry(invoc) => { + if force { + self.cx.span_bug( + invoc.span(), + "expansion entered force mode but is still stuck", + ); + } else { + // Cannot expand, will retry this invocation later. + undetermined_invocations.push((invoc, Some(ext))); + continue; + } + } }; progress = true; @@ -596,29 +579,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment_with_placeholders } - fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) { - let attr = self.cx.sess.find_by_name(item.attrs(), sym::derive); - let span = attr.map_or(item.span(), |attr| attr.span); - let mut err = struct_span_err!( - self.cx.sess, - span, - E0774, - "`derive` may only be applied to structs, enums and unions", - ); - if let Some(ast::Attribute { style: ast::AttrStyle::Inner, .. }) = attr { - let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, - "try an outer attribute", - suggestion, - // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT - Applicability::MaybeIncorrect, - ); - } - err.emit(); - } - fn resolve_imports(&mut self) { if self.monotonic { self.cx.resolver.resolve_imports(); @@ -633,7 +593,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { &mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId], - ) -> (AstFragment, Vec<(Invocation, Option)>) { + ) -> (AstFragment, Vec<(Invocation, Option>)>) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -733,7 +693,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext { + InvocationKind::Attr { attr, mut item, derives } => match ext { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); @@ -764,12 +724,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ExpandResult::Retry(item) => { // Reassemble the original invocation for retrying. return ExpandResult::Retry(Invocation { - kind: InvocationKind::Attr { - attr, - item, - derives, - after_derive, - }, + kind: InvocationKind::Attr { attr, item, derives }, ..invoc }); } @@ -813,7 +768,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::DeriveContainer { .. } => unreachable!(), }) } @@ -1011,29 +965,13 @@ pub fn ensure_complete_parse<'a>( struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, cfg: StripUnconfigured<'a>, - invocations: Vec<(Invocation, Option)>, + invocations: Vec<(Invocation, Option>)>, monotonic: bool, } impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - // Expansion data for all the collected invocations is set upon their resolution, - // with exception of the derive container case which is not resolved and can get - // its expansion data immediately. - let expn_data = match &kind { - InvocationKind::DeriveContainer { item, .. } => { - let mut expn_data = ExpnData::default( - ExpnKind::Macro(MacroKind::Attr, sym::derive), - item.span(), - self.cx.sess.parse_sess.edition, - None, - ); - expn_data.parent = self.cx.current_expansion.id; - Some(expn_data) - } - _ => None, - }; - let expn_id = ExpnId::fresh(expn_data); + let expn_id = ExpnId::fresh(None); let vis = kind.placeholder_visibility(); self.invocations.push(( Invocation { @@ -1061,64 +999,44 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_attr( &mut self, - (attr, derives, after_derive): (Option, Vec, bool), + (attr, derives): (ast::Attribute, Vec), item: Annotatable, kind: AstFragmentKind, ) -> AstFragment { - self.collect( - kind, - match attr { - Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive }, - None => InvocationKind::DeriveContainer { derives, item }, - }, - ) - } - - fn find_attr_invoc( - &self, - attrs: &mut Vec, - after_derive: &mut bool, - ) -> Option { - attrs - .iter() - .position(|a| { - if a.has_name(sym::derive) { - *after_derive = true; - } - !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a) - }) - .map(|i| attrs.remove(i)) - } - - /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. - fn take_first_attr( - &mut self, - item: &mut impl HasAttrs, - ) -> Option<(Option, Vec, /* after_derive */ bool)> { - let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); - - item.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); - traits = collect_derives(&mut self.cx, &mut attrs); - }); - - if attr.is_some() || !traits.is_empty() { Some((attr, traits, after_derive)) } else { None } + self.collect(kind, InvocationKind::Attr { attr, item, derives }) } - /// Alternative to `take_first_attr()` that ignores `#[derive]` so invocations fallthrough - /// to the unused-attributes lint (making it an error on statements and expressions - /// is a breaking change) - fn take_first_attr_no_derive( - &mut self, - nonitem: &mut impl HasAttrs, - ) -> Option<(Option, Vec, /* after_derive */ bool)> { - let (mut attr, mut after_derive) = (None, false); - - nonitem.visit_attrs(|mut attrs| { - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); + /// If `item` is an attribute invocation, remove the attribute and return it together with + /// derives following it. We have to collect the derives in order to resolve legacy derive + /// helpers (helpers written before derives that introduce them). + fn take_first_attr(&mut self, item: &mut impl HasAttrs) -> Option<(ast::Attribute, Vec)> { + let mut attr = None; + + item.visit_attrs(|attrs| { + attr = attrs + .iter() + .position(|a| !self.cx.sess.is_attr_known(a) && !is_builtin_attr(a)) + .map(|attr_pos| { + let attr = attrs.remove(attr_pos); + let following_derives = attrs[attr_pos..] + .iter() + .filter(|a| a.has_name(sym::derive)) + .flat_map(|a| a.meta_item_list().unwrap_or_default()) + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(ast::MetaItem { + kind: MetaItemKind::Word, + path, + .. + }) => Some(path), + _ => None, + }) + .collect(); + + (attr, following_derives) + }) }); - attr.map(|attr| (Some(attr), Vec::new(), after_derive)) + attr } fn configure(&mut self, node: T) -> Option { @@ -1132,17 +1050,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { for attr in attrs.iter() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); validate_attr::check_meta(&self.cx.sess.parse_sess, attr); - - // macros are expanded before any lint passes so this warning has to be hardcoded - if attr.has_name(sym::derive) { - self.cx - .parse_sess() - .span_diagnostic - .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") - .note("this may become a hard error in a future release") - .emit(); - } - if attr.doc_str().is_some() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( &UNUSED_DOC_COMMENTS, @@ -1162,12 +1069,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { visit_clobber(expr.deref_mut(), |mut expr| { self.cfg.configure_expr_kind(&mut expr.kind); - if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { + if let Some(attr) = self.take_first_attr(&mut expr) { // Collect the invoc regardless of whether or not attributes are permitted here // expansion will eat the attribute so it won't error later. - if let Some(attr) = attr.0.as_ref() { - self.cfg.maybe_emit_expr_attr_err(attr) - } + self.cfg.maybe_emit_expr_attr_err(&attr.0); // AstFragmentKind::Expr requires the macro to emit an expression. return self @@ -1263,10 +1168,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { expr.filter_map(|mut expr| { self.cfg.configure_expr_kind(&mut expr.kind); - if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { - if let Some(attr) = attr.0.as_ref() { - self.cfg.maybe_emit_expr_attr_err(attr) - } + if let Some(attr) = self.take_first_attr(&mut expr) { + self.cfg.maybe_emit_expr_attr_err(&attr.0); return self .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr) @@ -1308,15 +1211,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { - let attr = if stmt.is_item() { - self.take_first_attr(&mut stmt) - } else { - // Ignore derives on non-item statements for backwards compatibility. - // This will result in a unused attribute warning - self.take_first_attr_no_derive(&mut stmt) - }; - - if let Some(attr) = attr { + if let Some(attr) = self.take_first_attr(&mut stmt) { return self .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts) .make_stmts(); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 6779734cfc176..8cbaa7c945a81 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -1,16 +1,14 @@ use crate::base::{self, *}; use crate::proc_macro_server; +use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree}; -use rustc_ast::{self as ast, *}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability, ErrorReported}; -use rustc_lexer::is_ident; +use rustc_errors::ErrorReported; use rustc_parse::nt_to_tokenstream; use rustc_parse::parser::ForceCollect; -use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; @@ -142,91 +140,3 @@ impl MultiItemModifier for ProcMacroDerive { ExpandResult::Ready(items) } } - -crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) -> Vec { - let mut result = Vec::new(); - attrs.retain(|attr| { - if !attr.has_name(sym::derive) { - return true; - } - - // 1) First let's ensure that it's a meta item. - let nmis = match attr.meta_item_list() { - None => { - cx.struct_span_err(attr.span, "malformed `derive` attribute input") - .span_suggestion( - attr.span, - "missing traits to be derived", - "#[derive(Trait1, Trait2, ...)]".to_owned(), - Applicability::HasPlaceholders, - ) - .emit(); - return false; - } - Some(x) => x, - }; - - let mut error_reported_filter_map = false; - let mut error_reported_map = false; - let traits = nmis - .into_iter() - // 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`. - .filter_map(|nmi| match nmi { - NestedMetaItem::Literal(lit) => { - error_reported_filter_map = true; - let mut err = struct_span_err!( - cx.sess, - lit.span, - E0777, - "expected path to a trait, found literal", - ); - let token = lit.token.to_string(); - if token.starts_with('"') - && token.len() > 2 - && is_ident(&token[1..token.len() - 1]) - { - err.help(&format!("try using `#[derive({})]`", &token[1..token.len() - 1])); - } else { - err.help("for example, write `#[derive(Debug)]` for `Debug`"); - } - err.emit(); - None - } - NestedMetaItem::MetaItem(mi) => Some(mi), - }) - // 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]` - // but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`. - // In this case we can still at least determine that the user - // wanted this trait to be derived, so let's keep it. - .map(|mi| { - let mut traits_dont_accept = |title, action| { - error_reported_map = true; - let sp = mi.span.with_lo(mi.path.span.hi()); - cx.struct_span_err(sp, title) - .span_suggestion( - sp, - action, - String::new(), - Applicability::MachineApplicable, - ) - .emit(); - }; - match &mi.kind { - MetaItemKind::List(..) => traits_dont_accept( - "traits in `#[derive(...)]` don't accept arguments", - "remove the arguments", - ), - MetaItemKind::NameValue(..) => traits_dont_accept( - "traits in `#[derive(...)]` don't accept values", - "remove the value", - ), - MetaItemKind::Word => {} - } - mi.path - }); - - result.extend(traits); - !error_reported_filter_map && !error_reported_map - }); - result -} diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3ed5320da73b3..ac50703b5444e 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -188,7 +188,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), // Macros: - ungated!(derive, Normal, template!(List: "Trait1, Trait2, ...")), ungated!(automatically_derived, Normal, template!(Word)), // FIXME(#14407) ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 58a9064b9195b..254220839aa47 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -636,6 +636,9 @@ pub trait LintContext: Sized { db.span_label(span, "ABI should be specified here"); db.help(&format!("the default ABI is {}", default_abi.name())); } + BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => { + db.span_label(span, "the attribute is introduced here"); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index da62ad3a6b1cd..f0a5ea150b719 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1,12 +1,11 @@ // ignore-tidy-filelength + //! Some lints that are built in to the compiler. //! //! These are the built-in lints that are emitted direct in the main //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -// ignore-tidy-filelength - use crate::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; use rustc_span::symbol::sym; @@ -2922,6 +2921,52 @@ declare_lint! { }; } +declare_lint! { + /// The `legacy_derive_helpers` lint detects derive helper attributes + /// that are used before they are introduced. + /// + /// ### Example + /// + /// ```rust,ignore (needs extern crate) + /// #[serde(rename_all = "camelCase")] + /// #[derive(Deserialize)] + /// struct S { /* fields */ } + /// ``` + /// + /// produces: + /// + /// ```text + /// warning: derive helper attribute is used before it is introduced + /// --> $DIR/legacy-derive-helpers.rs:1:3 + /// | + /// 1 | #[serde(rename_all = "camelCase")] + /// | ^^^^^ + /// ... + /// 2 | #[derive(Deserialize)] + /// | ----------- the attribute is introduced here + /// ``` + /// + /// ### Explanation + /// + /// Attributes like this work for historical reasons, but attribute expansion works in + /// left-to-right order in general, so, to resolve `#[serde]`, compiler has to try to "look + /// into the future" at not yet expanded part of the item , but such attempts are not always + /// reliable. + /// + /// To fix the warning place the helper attribute after its corresponding derive. + /// ```rust,ignore (needs extern crate) + /// #[derive(Deserialize)] + /// #[serde(rename_all = "camelCase")] + /// struct S { /* fields */ } + /// ``` + pub LEGACY_DERIVE_HELPERS, + Warn, + "detects derive helper attributes that are used before they are introduced", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #79202 ", + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -3012,6 +3057,7 @@ declare_lint_pass! { MISSING_ABI, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, DISJOINT_CAPTURE_DROP_REORDER, + LEGACY_DERIVE_HELPERS, ] } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 9d60a51a0afb3..594e2cbd3aed9 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -256,6 +256,7 @@ pub enum BuiltinLintDiagnostics { MissingAbi(Span, Abi), UnusedDocComment(Span), PatternsInFnsWithoutBody(Span, Ident), + LegacyDeriveHelpers(Span), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 1b26fb3337043..523eb9dba35fd 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -306,13 +306,11 @@ impl<'a> Parser<'a> { } pub fn maybe_needs_tokens(attrs: &[ast::Attribute]) -> bool { - // One of the attributes may either itself be a macro, or apply derive macros (`derive`), + // One of the attributes may either itself be a macro, // or expand to macro attributes (`cfg_attr`). attrs.iter().any(|attr| { attr.ident().map_or(true, |ident| { - ident.name == sym::derive - || ident.name == sym::cfg_attr - || !rustc_feature::is_builtin_attr_name(ident.name) + ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name) }) }) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2be669a1726a1..819fabdd1f177 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -967,6 +967,8 @@ pub struct Resolver<'a> { output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap>, + /// Resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`. + derive_resolutions: FxHashMap, ast::Path)>>, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, @@ -1295,6 +1297,7 @@ impl<'a> Resolver<'a> { invocation_parent_scopes: Default::default(), output_macro_rules_scopes: Default::default(), helper_attrs: Default::default(), + derive_resolutions: Default::default(), local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), potentially_unused_imports: Vec::new(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d76db7c645abc..6d3fde33f4d1e 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -14,8 +14,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; -use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand}; -use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::base::{Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind}; use rustc_feature::is_builtin_attr_name; @@ -24,7 +23,8 @@ use rustc_hir::def_id; use rustc_hir::PrimTy; use rustc_middle::middle::stability; use rustc_middle::ty; -use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::Edition; @@ -227,7 +227,7 @@ impl<'a> ResolverExpand for Resolver<'a> { invoc: &Invocation, eager_expansion_root: ExpnId, force: bool, - ) -> Result { + ) -> Result, Indeterminate> { let invoc_id = invoc.expansion_data.id; let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) { Some(parent_scope) => *parent_scope, @@ -244,65 +244,15 @@ impl<'a> ResolverExpand for Resolver<'a> { } }; - let (path, kind, inner_attr, derives, after_derive) = match invoc.kind { - InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => ( + let (path, kind, inner_attr, derives) = match invoc.kind { + InvocationKind::Attr { ref attr, ref derives, .. } => ( &attr.get_normal_item().path, MacroKind::Attr, attr.style == ast::AttrStyle::Inner, self.arenas.alloc_ast_paths(derives), - after_derive, ), - InvocationKind::Bang { ref mac, .. } => { - (&mac.path, MacroKind::Bang, false, &[][..], false) - } - InvocationKind::Derive { ref path, .. } => { - (path, MacroKind::Derive, false, &[][..], false) - } - InvocationKind::DeriveContainer { ref derives, .. } => { - // Block expansion of the container until we resolve all derives in it. - // This is required for two reasons: - // - Derive helper attributes are in scope for the item to which the `#[derive]` - // is applied, so they have to be produced by the container's expansion rather - // than by individual derives. - // - Derives in the container need to know whether one of them is a built-in `Copy`. - // FIXME: Try to avoid repeated resolutions for derives here and in expansion. - let mut exts = Vec::new(); - let mut helper_attrs = Vec::new(); - for path in derives { - exts.push( - match self.resolve_macro_path( - path, - Some(MacroKind::Derive), - &parent_scope, - true, - force, - ) { - Ok((Some(ext), _)) => { - let span = path - .segments - .last() - .unwrap() - .ident - .span - .normalize_to_macros_2_0(); - helper_attrs.extend( - ext.helper_attrs.iter().map(|name| Ident::new(*name, span)), - ); - if ext.builtin_name == Some(sym::Copy) { - self.containers_deriving_copy.insert(invoc_id); - } - ext - } - Ok(_) | Err(Determinacy::Determined) => { - self.dummy_ext(MacroKind::Derive) - } - Err(Determinacy::Undetermined) => return Err(Indeterminate), - }, - ) - } - self.helper_attrs.insert(invoc_id, helper_attrs); - return Ok(InvocationRes::DeriveContainer(exts)); - } + InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang, false, &[][..]), + InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, false, &[][..]), }; // Derives are not included when `invocations` are collected, so we have to add them here. @@ -328,14 +278,11 @@ impl<'a> ResolverExpand for Resolver<'a> { )); if let Res::Def(_, _) = res { - if after_derive { - self.session.span_err(span, "macro attributes must be placed before `#[derive]`"); - } let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod; self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); } - Ok(InvocationRes::Single(ext)) + Ok(ext) } fn check_unused_macros(&mut self) { @@ -344,7 +291,7 @@ impl<'a> ResolverExpand for Resolver<'a> { } } - fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId { + fn lint_node_id(&self, expn_id: ExpnId) -> NodeId { // FIXME - make this more precise. This currently returns the NodeId of the // nearest closing item - we should try to return the closest parent of the ExpnId self.invocation_parents @@ -356,6 +303,63 @@ impl<'a> ResolverExpand for Resolver<'a> { self.containers_deriving_copy.contains(&expn_id) } + fn resolve_derives( + &mut self, + expn_id: ExpnId, + derives: Vec, + force: bool, + ) -> Result<(), Indeterminate> { + // Block expansion of the container until we resolve all derives in it. + // This is required for two reasons: + // - Derive helper attributes are in scope for the item to which the `#[derive]` + // is applied, so they have to be produced by the container's expansion rather + // than by individual derives. + // - Derives in the container need to know whether one of them is a built-in `Copy`. + // FIXME: Try to cache intermediate results to avoid resolving same derives multiple times. + let parent_scope = self.invocation_parent_scopes[&expn_id]; + let mut exts = Vec::new(); + let mut helper_attrs = Vec::new(); + let mut has_derive_copy = false; + for path in derives { + exts.push(( + match self.resolve_macro_path( + &path, + Some(MacroKind::Derive), + &parent_scope, + true, + force, + ) { + Ok((Some(ext), _)) => { + let span = + path.segments.last().unwrap().ident.span.normalize_to_macros_2_0(); + helper_attrs + .extend(ext.helper_attrs.iter().map(|name| Ident::new(*name, span))); + has_derive_copy |= ext.builtin_name == Some(sym::Copy); + ext + } + Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), + Err(Determinacy::Undetermined) => return Err(Indeterminate), + }, + path, + )) + } + self.derive_resolutions.insert(expn_id, exts); + self.helper_attrs.insert(expn_id, helper_attrs); + // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive + // has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`. + if has_derive_copy || self.has_derive_copy(parent_scope.expansion) { + self.containers_deriving_copy.insert(expn_id); + } + Ok(()) + } + + fn take_derive_resolutions( + &mut self, + expn_id: ExpnId, + ) -> Option, ast::Path)>> { + self.derive_resolutions.remove(&expn_id) + } + // The function that implements the resolution logic of `#[cfg_accessible(path)]`. // Returns true if the path can certainly be resolved in one of three namespaces, // returns false if the path certainly cannot be resolved in any of the three namespaces. @@ -818,6 +822,8 @@ impl<'a> Resolver<'a> { let is_builtin = |res| { matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..))) }; + let derive_helper = + Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); let derive_helper_compat = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat); @@ -826,7 +832,7 @@ impl<'a> Resolver<'a> { } else if is_builtin(innermost_res) || is_builtin(res) { Some(AmbiguityKind::BuiltinAttr) } else if innermost_res == derive_helper_compat - || res == derive_helper_compat + || res == derive_helper_compat && innermost_res != derive_helper { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) @@ -992,6 +998,15 @@ impl<'a> Resolver<'a> { let res = binding.res(); let seg = Segment::from_ident(ident); check_consistency(self, &[seg], ident.span, kind, initial_res, res); + if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) { + self.lint_buffer.buffer_lint_with_diagnostic( + LEGACY_DERIVE_HELPERS, + self.lint_node_id(parent_scope.expansion), + ident.span, + "derive helper attribute is used before it is introduced", + BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span), + ); + } } Err(..) => { let expected = kind.descr_expected(); @@ -1078,7 +1093,7 @@ impl<'a> Resolver<'a> { crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) { // Reserve some names that are not quite covered by the general check // performed on `Resolver::builtin_attrs`. - if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive { + if ident.name == sym::cfg || ident.name == sym::cfg_attr { let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind()); if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { self.session.span_err( diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 6a7e4b2ba2573..7aaf5a5fd4614 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1324,6 +1324,14 @@ pub(crate) mod builtin { (false) => {{ /* compiler built-in */ }}; } + /// Attribute macro used to apply derive macros. + #[cfg(not(bootstrap))] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_builtin_macro] + pub macro derive($item:item) { + /* compiler built-in */ + } + /// Attribute macro applied to a function to turn it into a unit test. #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(test, rustc_attrs)] diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index b4fff3d67b555..a1fbd8dec7505 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -69,6 +69,11 @@ pub use crate::macros::builtin::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::macros::builtin::derive; + #[unstable( feature = "cfg_accessible", issue = "64797", diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 26302d0ecf2b1..ef9aec54a4ca2 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -54,6 +54,11 @@ pub use core::prelude::v1::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(hidden)] +pub use core::prelude::v1::derive; + #[unstable( feature = "cfg_accessible", issue = "64797", diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index f4b8dc9a3ad2b..297fc95006b02 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -96,8 +96,8 @@ pub struct Deprecation { pub note: Option, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum Visibility { Public, /// For the most part items are private by default. The exceptions are associated items of @@ -112,8 +112,8 @@ pub enum Visibility { }, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum GenericArgs { /// <'a, 32, B: Copy, C = u32> AngleBracketed { args: Vec, bindings: Vec }, @@ -121,8 +121,8 @@ pub enum GenericArgs { Parenthesized { inputs: Vec, output: Option }, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum GenericArg { Lifetime(String), Type(Type), @@ -144,8 +144,8 @@ pub struct TypeBinding { pub binding: TypeBindingKind, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum TypeBindingKind { Equality(Type), Constraint(Vec), @@ -154,8 +154,8 @@ pub enum TypeBindingKind { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Id(pub String); -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum ItemKind { Module, ExternCrate, @@ -184,8 +184,8 @@ pub enum ItemKind { Keyword, } -#[serde(untagged)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(untagged)] pub enum ItemEnum { ModuleItem(Module), ExternCrateItem { @@ -264,17 +264,17 @@ pub struct Enum { pub impls: Vec, } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "variant_kind", content = "variant_inner")] -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Variant { Plain, Tuple(Vec), Struct(Vec), } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum StructType { Plain, Tuple, @@ -310,24 +310,24 @@ pub struct GenericParamDef { pub kind: GenericParamDefKind, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum GenericParamDefKind { Lifetime, Type { bounds: Vec, default: Option }, Const(Type), } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec }, RegionPredicate { lifetime: String, bounds: Vec }, EqPredicate { lhs: Type, rhs: Type }, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum GenericBound { TraitBound { #[serde(rename = "trait")] @@ -339,17 +339,17 @@ pub enum GenericBound { Outlives(String), } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum TraitBoundModifier { None, Maybe, MaybeConst, } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "kind", content = "inner")] -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Type { /// Structs, enums, and traits ResolvedPath { @@ -448,8 +448,8 @@ pub struct Impl { pub blanket_impl: Option, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub struct Import { /// The full path being imported. pub span: String, @@ -468,8 +468,8 @@ pub struct ProcMacro { pub helpers: Vec, } -#[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] pub enum MacroKind { /// A bang macro `foo!()`. Bang, diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs index 717da367feec5..d11cfd77c5bf9 100644 --- a/src/test/run-make-fulldeps/simd-ffi/simd.rs +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -75,3 +75,8 @@ auto trait Freeze {} macro_rules! Copy { () => {}; } +#[macro_export] +#[rustc_builtin_macro] +macro_rules! derive { + () => {}; +} diff --git a/src/test/ui/derives/derive-deadlock.rs b/src/test/ui/derives/derive-deadlock.rs new file mode 100644 index 0000000000000..0137b1e5bfbf3 --- /dev/null +++ b/src/test/ui/derives/derive-deadlock.rs @@ -0,0 +1,6 @@ +use std as derive; + +#[derive(Default)] //~ ERROR cannot determine resolution for the attribute macro `derive` +struct S; + +fn main() {} diff --git a/src/test/ui/derives/derive-deadlock.stderr b/src/test/ui/derives/derive-deadlock.stderr new file mode 100644 index 0000000000000..8d062491c6a7c --- /dev/null +++ b/src/test/ui/derives/derive-deadlock.stderr @@ -0,0 +1,10 @@ +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/derive-deadlock.rs:3:3 + | +LL | #[derive(Default)] + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to previous error + diff --git a/src/test/ui/derives/derive-multiple-with-packed.rs b/src/test/ui/derives/derive-multiple-with-packed.rs new file mode 100644 index 0000000000000..e762ee357caab --- /dev/null +++ b/src/test/ui/derives/derive-multiple-with-packed.rs @@ -0,0 +1,10 @@ +// check-pass + +#[derive(Clone, Copy)] +#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]` +#[repr(packed)] +struct CacheRecordHeader { + field: u64, +} + +fn main() {} diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.rs b/src/test/ui/derives/deriving-meta-empty-trait-list.rs index 4f2e31e8efb15..0306ce717d049 100644 --- a/src/test/ui/derives/deriving-meta-empty-trait-list.rs +++ b/src/test/ui/derives/deriving-meta-empty-trait-list.rs @@ -1,6 +1,8 @@ +// check-pass + #![deny(unused)] -#[derive()] //~ ERROR unused attribute +#[derive()] // OK struct _Bar; pub fn main() {} diff --git a/src/test/ui/derives/deriving-meta-empty-trait-list.stderr b/src/test/ui/derives/deriving-meta-empty-trait-list.stderr deleted file mode 100644 index 1fd7d58c86a37..0000000000000 --- a/src/test/ui/derives/deriving-meta-empty-trait-list.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: unused attribute - --> $DIR/deriving-meta-empty-trait-list.rs:3:1 - | -LL | #[derive()] - | ^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/deriving-meta-empty-trait-list.rs:1:9 - | -LL | #![deny(unused)] - | ^^^^^^ - = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` - -error: aborting due to previous error - diff --git a/src/test/ui/derives/issue-36617.rs b/src/test/ui/derives/issue-36617.rs index 1102f3c4640a1..08fc82e91f623 100644 --- a/src/test/ui/derives/issue-36617.rs +++ b/src/test/ui/derives/issue-36617.rs @@ -1,4 +1,3 @@ -#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions - //~| ERROR cannot determine resolution for the derive macro `Copy` +#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive` fn main() {} diff --git a/src/test/ui/derives/issue-36617.stderr b/src/test/ui/derives/issue-36617.stderr index dc6ef16925913..0716764b42704 100644 --- a/src/test/ui/derives/issue-36617.stderr +++ b/src/test/ui/derives/issue-36617.stderr @@ -1,17 +1,10 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-36617.rs:1:1 +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/issue-36617.rs:1:4 | LL | #![derive(Copy)] - | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]` - -error: cannot determine resolution for the derive macro `Copy` - --> $DIR/issue-36617.rs:1:11 - | -LL | #![derive(Copy)] - | ^^^^ + | ^^^^^^ | = note: import resolution is stuck, try simplifying macro imports -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs index c5d9e0db4d389..5404b8c04bb76 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs @@ -6,6 +6,7 @@ mod derive { mod inner { #![derive(Debug)] } //~^ ERROR `derive` may only be applied to structs, enums and unions + //~| ERROR inner macro attributes are unstable #[derive(Debug)] //~^ ERROR `derive` may only be applied to structs, enums and unions diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr index ffec76f409ef7..9b1f4f46219d2 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr @@ -4,30 +4,40 @@ error[E0774]: `derive` may only be applied to structs, enums and unions LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ +error[E0658]: inner macro attributes are unstable + --> $DIR/issue-43106-gating-of-derive.rs:7:20 + | +LL | mod inner { #![derive(Debug)] } + | ^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + error[E0774]: `derive` may only be applied to structs, enums and unions --> $DIR/issue-43106-gating-of-derive.rs:7:17 | LL | mod inner { #![derive(Debug)] } - | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]` + | ^^^^^^^^^^^^^^^^^ error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:10:5 + --> $DIR/issue-43106-gating-of-derive.rs:11:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:23:5 + --> $DIR/issue-43106-gating-of-derive.rs:24:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43106-gating-of-derive.rs:27:5 + --> $DIR/issue-43106-gating-of-derive.rs:28:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0774`. +Some errors have detailed explanations: E0658, E0774. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-49934-errors.rs b/src/test/ui/issues/issue-49934-errors.rs index bf95f8fa7e1ec..dd14bac5e3a9f 100644 --- a/src/test/ui/issues/issue-49934-errors.rs +++ b/src/test/ui/issues/issue-49934-errors.rs @@ -1,11 +1,8 @@ -fn foo<#[derive(Debug)] T>() { -//~^ ERROR `derive` may only be applied to structs, enums and unions +fn foo<#[derive(Debug)] T>() { //~ ERROR expected non-macro attribute, found attribute macro match 0 { - #[derive(Debug)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR expected non-macro attribute, found attribute macro _ => (), } } -fn main() { -} +fn main() {} diff --git a/src/test/ui/issues/issue-49934-errors.stderr b/src/test/ui/issues/issue-49934-errors.stderr index 71cd2d3034243..8c4c54170a101 100644 --- a/src/test/ui/issues/issue-49934-errors.stderr +++ b/src/test/ui/issues/issue-49934-errors.stderr @@ -1,15 +1,14 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-49934-errors.rs:1:8 +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-49934-errors.rs:1:10 | LL | fn foo<#[derive(Debug)] T>() { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^ not a non-macro attribute -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-49934-errors.rs:4:9 +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-49934-errors.rs:3:11 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^ not a non-macro attribute error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs index 5b253750db0b6..ec73e670634df 100644 --- a/src/test/ui/issues/issue-49934.rs +++ b/src/test/ui/issues/issue-49934.rs @@ -1,7 +1,4 @@ -// check-pass - #![feature(stmt_expr_attributes)] -#![warn(unused_attributes)] //~ NOTE the lint level is defined here fn main() { // fold_stmt (Item) @@ -10,26 +7,24 @@ fn main() { struct Foo; // fold_stmt (Mac) - #[derive(Debug)] - //~^ WARN `#[derive]` does nothing on macro invocations - //~| NOTE this may become a hard error in a future release + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions println!("Hello, world!"); // fold_stmt (Semi) - #[derive(Debug)] //~ WARN unused attribute + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions "Hello, world!"; // fold_stmt (Local) - #[derive(Debug)] //~ WARN unused attribute + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions let _ = "Hello, world!"; // visit_expr let _ = #[derive(Debug)] "Hello, world!"; - //~^ WARN unused attribute + //~^ ERROR `derive` may only be applied to structs, enums and unions let _ = [ // filter_map_expr - #[derive(Debug)] //~ WARN unused attribute - "Hello, world!" + #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + "Hello, world!", ]; } diff --git a/src/test/ui/issues/issue-49934.stderr b/src/test/ui/issues/issue-49934.stderr index 8a5596521ec55..7746ad287ab79 100644 --- a/src/test/ui/issues/issue-49934.stderr +++ b/src/test/ui/issues/issue-49934.stderr @@ -1,40 +1,33 @@ -warning: `#[derive]` does nothing on macro invocations - --> $DIR/issue-49934.rs:13:5 +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934.rs:10:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ - | - = note: this may become a hard error in a future release -warning: unused attribute - --> $DIR/issue-49934.rs:19:5 +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934.rs:14:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-49934.rs:4:9 - | -LL | #![warn(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ -warning: unused attribute - --> $DIR/issue-49934.rs:23:5 +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934.rs:18:5 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -warning: unused attribute - --> $DIR/issue-49934.rs:27:13 +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934.rs:22:13 | LL | let _ = #[derive(Debug)] "Hello, world!"; | ^^^^^^^^^^^^^^^^ -warning: unused attribute - --> $DIR/issue-49934.rs:32:9 +error[E0774]: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-49934.rs:27:9 | LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -warning: 5 warnings emitted +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/macros/builtin-std-paths-fail.stderr b/src/test/ui/macros/builtin-std-paths-fail.stderr index 9831e46ec30a1..4f1a76b0d6e08 100644 --- a/src/test/ui/macros/builtin-std-paths-fail.stderr +++ b/src/test/ui/macros/builtin-std-paths-fail.stderr @@ -1,3 +1,15 @@ +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:4:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + error[E0433]: failed to resolve: could not find `bench` in `core` --> $DIR/builtin-std-paths-fail.rs:7:9 | @@ -23,28 +35,28 @@ LL | #[core::test] | ^^^^ could not find `test` in `core` error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:2:11 + --> $DIR/builtin-std-paths-fail.rs:4:11 | LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:4:11 + --> $DIR/builtin-std-paths-fail.rs:2:11 | LL | core::RustcDecodable, | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:4:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:14:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` - --> $DIR/builtin-std-paths-fail.rs:2:11 +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:10 | -LL | core::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` error[E0433]: failed to resolve: could not find `bench` in `std` --> $DIR/builtin-std-paths-fail.rs:19:8 @@ -70,18 +82,6 @@ error[E0433]: failed to resolve: could not find `test` in `std` LL | #[std::test] | ^^^^ could not find `test` in `std` -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:14:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - -error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` - --> $DIR/builtin-std-paths-fail.rs:16:10 - | -LL | std::RustcDecodable, - | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` - error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` --> $DIR/builtin-std-paths-fail.rs:16:10 | diff --git a/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs b/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs index 1fd7cddc7c937..fc4c3f4e64bf9 100644 --- a/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs +++ b/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs @@ -1,9 +1,6 @@ fn main() {} struct CLI { - #[derive(parse())] - //~^ ERROR traits in `#[derive(...)]` don't accept arguments - //~| ERROR cannot find derive macro `parse` in this scope + #[derive(parse())] //~ ERROR expected non-macro attribute, found attribute macro path: (), - //~^ ERROR `derive` may only be applied to structs, enums and unions } diff --git a/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr b/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr index db40ce0753045..04f7ebe019ea4 100644 --- a/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr +++ b/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr @@ -1,21 +1,8 @@ -error: traits in `#[derive(...)]` don't accept arguments - --> $DIR/issue-69341-malformed-derive-inert.rs:4:19 +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-69341-malformed-derive-inert.rs:4:7 | LL | #[derive(parse())] - | ^^ help: remove the arguments + | ^^^^^^ not a non-macro attribute -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-69341-malformed-derive-inert.rs:7:5 - | -LL | path: (), - | ^^^^^^^^ - -error: cannot find derive macro `parse` in this scope - --> $DIR/issue-69341-malformed-derive-inert.rs:4:14 - | -LL | #[derive(parse())] - | ^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr index 63be8f9ca14db..365cc099e9d3e 100644 --- a/src/test/ui/malformed/malformed-derive-entry.stderr +++ b/src/test/ui/malformed/malformed-derive-entry.stderr @@ -14,7 +14,7 @@ error: malformed `derive` attribute input --> $DIR/malformed-derive-entry.rs:11:1 | LL | #[derive] - | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]` + | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error[E0277]: the trait bound `Test1: Clone` is not satisfied --> $DIR/malformed-derive-entry.rs:1:10 diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr index 6f535e03e6aec..1764c3969cfee 100644 --- a/src/test/ui/malformed/malformed-special-attrs.stderr +++ b/src/test/ui/malformed/malformed-special-attrs.stderr @@ -18,13 +18,13 @@ error: malformed `derive` attribute input --> $DIR/malformed-special-attrs.rs:7:1 | LL | #[derive] - | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]` + | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error: malformed `derive` attribute input --> $DIR/malformed-special-attrs.rs:10:1 | LL | #[derive = ""] - | ^^^^^^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]` + | ^^^^^^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error: aborting due to 4 previous errors diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs new file mode 100644 index 0000000000000..0f0f27bff97be --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive.rs @@ -0,0 +1,28 @@ +// Macro attributes are allowed after `#[derive]` and +// `#[derive]` fully configures the item for following attributes. + +// check-pass +// compile-flags: -Z span-debug +// aux-build: test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_attr] +#[derive(Print)] +struct AttributeDerive { + #[cfg(FALSE)] + field: u8, +} + +#[derive(Print)] +#[print_attr] +struct DeriveAttribute { + #[cfg(FALSE)] + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout new file mode 100644 index 0000000000000..78c58c0a32fcf --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -0,0 +1,148 @@ +PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_attr", + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + }, +] diff --git a/src/test/ui/proc-macro/attribute-order-restricted.rs b/src/test/ui/proc-macro/attribute-order-restricted.rs deleted file mode 100644 index a3d4d23450ca6..0000000000000 --- a/src/test/ui/proc-macro/attribute-order-restricted.rs +++ /dev/null @@ -1,14 +0,0 @@ -// aux-build:test-macros.rs - -#[macro_use] -extern crate test_macros; - -#[identity_attr] // OK -#[derive(Clone)] -struct Before; - -#[derive(Clone)] -#[identity_attr] //~ ERROR macro attributes must be placed before `#[derive]` -struct After; - -fn main() {} diff --git a/src/test/ui/proc-macro/attribute-order-restricted.stderr b/src/test/ui/proc-macro/attribute-order-restricted.stderr deleted file mode 100644 index 9ca8a443e40fb..0000000000000 --- a/src/test/ui/proc-macro/attribute-order-restricted.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: macro attributes must be placed before `#[derive]` - --> $DIR/attribute-order-restricted.rs:11:1 - | -LL | #[identity_attr] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index 6147e96a74bf1..80d982d2504db 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -17,6 +17,8 @@ macro_rules! gen_helper_use { } #[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[derive(Empty)] struct S { #[empty_helper] // OK, no ambiguity, derive helpers have highest priority diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index f82f49aa77526..a49df9f2d4a33 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,17 +1,17 @@ error: cannot use a derive helper attribute through an import - --> $DIR/derive-helper-shadowing.rs:40:15 + --> $DIR/derive-helper-shadowing.rs:42:15 | LL | #[renamed] | ^^^^^^^ | note: the derive helper attribute imported here - --> $DIR/derive-helper-shadowing.rs:39:17 + --> $DIR/derive-helper-shadowing.rs:41:17 | LL | use empty_helper as renamed; | ^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `empty_helper` in this scope - --> $DIR/derive-helper-shadowing.rs:36:22 + --> $DIR/derive-helper-shadowing.rs:38:22 | LL | #[derive(GenHelperUse)] | ^^^^^^^^^^^^ @@ -30,13 +30,13 @@ LL | gen_helper_use!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution) - --> $DIR/derive-helper-shadowing.rs:24:13 + --> $DIR/derive-helper-shadowing.rs:26:13 | LL | use empty_helper; | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:20:10 + --> $DIR/derive-helper-shadowing.rs:22:10 | LL | #[derive(Empty)] | ^^^^^ @@ -54,7 +54,7 @@ LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:20:10 + --> $DIR/derive-helper-shadowing.rs:22:10 | LL | #[derive(Empty)] | ^^^^^ @@ -65,6 +65,19 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error: aborting due to 5 previous errors +warning: derive helper attribute is used before it is introduced + --> $DIR/derive-helper-shadowing.rs:19:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/derive-helper-vs-legacy.rs b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs new file mode 100644 index 0000000000000..98836bcb8937d --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] +#[empty_helper] // OK, this is both derive helper and legacy derive helper +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-multiple-with-packed.rs b/src/test/ui/proc-macro/derive-multiple-with-packed.rs new file mode 100644 index 0000000000000..23578aa0e9fb8 --- /dev/null +++ b/src/test/ui/proc-macro/derive-multiple-with-packed.rs @@ -0,0 +1,11 @@ +// check-pass + +#[derive(Clone, Copy)] +#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]` +#[derive(PartialEq)] // OK too +#[repr(packed)] +struct CacheRecordHeader { + field: u64, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs index 3a1c56efce8c2..40c42d82f68de 100644 --- a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -4,8 +4,10 @@ extern crate test_macros; use test_macros::empty_attr as empty_helper; -#[derive(Empty)] #[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(Empty)] struct S; fn main() {} diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr index 012fb105b128d..ceb6d789785cc 100644 --- a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -1,11 +1,11 @@ error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:3 + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:10 + --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10 | LL | #[derive(Empty)] | ^^^^^ @@ -16,6 +16,19 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error: aborting due to previous error +warning: derive helper attribute is used before it is introduced + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs index a051d23bac0ae..649e731840337 100644 --- a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs @@ -13,7 +13,8 @@ #[macro_use] extern crate test_macros; -#[print_helper(a)] +#[print_helper(a)] //~ WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[cfg_attr(not(FALSE), allow(dead_code))] #[print_attr] #[derive(Print)] diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr new file mode 100644 index 0000000000000..5227da7d76677 --- /dev/null +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr @@ -0,0 +1,15 @@ +warning: derive helper attribute is used before it is introduced + --> $DIR/issue-75930-derive-cfg.rs:16:3 + | +LL | #[print_helper(a)] + | ^^^^^^^^^^^^ +... +LL | #[derive(Print)] + | ----- the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: 1 warning emitted + diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout index 5f513684cfa6f..19aa4dfb60e36 100644 --- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout +++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -26,77 +26,77 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:17:1: 17:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:18:1: 18:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:17:24: 17:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:18:24: 18:29 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "dead_code", - span: $DIR/issue-75930-derive-cfg.rs:17:30: 17:39 (#0), + span: $DIR/issue-75930-derive-cfg.rs:18:30: 18:39 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:17:29: 17:40 (#0), + span: $DIR/issue-75930-derive-cfg.rs:18:29: 18:40 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:17:1: 17:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:18:1: 18:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:1: 20:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "derive", - span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:9 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:3: 20:9 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "Print", - span: $DIR/issue-75930-derive-cfg.rs:19:10: 19:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:10: 20:15 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:19:9: 19:16 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:9: 20:16 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:20:2: 20:17 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:20:1: 20:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:20:3: 20:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:3: 21:15 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "b", - span: $DIR/issue-75930-derive-cfg.rs:20:16: 20:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:16: 21:17 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:20:15: 20:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:15: 21:18 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:20:2: 20:19 (#0), + span: $DIR/issue-75930-derive-cfg.rs:21:2: 21:19 (#0), }, Punct { ch: '#', @@ -125,59 +125,59 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:7 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 22:7 (#0), }, Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:21:8: 21:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:8: 22:11 (#0), }, Punct { ch: '<', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:21:11: 21:12 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:11: 22:12 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:12: 21:13 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:12: 22:13 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:14: 21:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:14: 22:17 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:18: 21:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:18: 22:23 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:17: 21:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:17: 22:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:13: 21:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:13: 22:25 (#0), }, Ident { ident: "A", - span: $DIR/issue-75930-derive-cfg.rs:21:26: 21:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:26: 22:27 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:27: 21:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:27: 22:28 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:29: 22:30 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:30: 22:31 (#0), }, Group { delimiter: Brace, @@ -185,128 +185,128 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:22:5: 22:6 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:5: 23:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:22:7: 22:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:7: 23:10 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:22:11: 22:16 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:11: 23:16 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:22:10: 22:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:17 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:22:6: 22:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:6: 23:18 (#0), }, Ident { ident: "first", - span: $DIR/issue-75930-derive-cfg.rs:22:19: 22:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:19: 23:24 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:22:24: 22:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:24: 23:25 (#0), }, Ident { ident: "String", - span: $DIR/issue-75930-derive-cfg.rs:22:26: 22:32 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:26: 23:32 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:22:32: 22:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:23:32: 23:33 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:23:5: 23:6 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:5: 24:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg_attr", - span: $DIR/issue-75930-derive-cfg.rs:23:7: 23:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:7: 24:15 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:23:16: 23:21 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:21 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:23:21: 23:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:21: 24:22 (#0), }, Ident { ident: "deny", - span: $DIR/issue-75930-derive-cfg.rs:23:23: 23:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:23: 24:27 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: $DIR/issue-75930-derive-cfg.rs:23:28: 23:36 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:28: 24:36 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:23:27: 23:37 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:27: 24:37 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:23:15: 23:38 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:38 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:23:6: 23:39 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:6: 24:39 (#0), }, Ident { ident: "second", - span: $DIR/issue-75930-derive-cfg.rs:23:40: 23:46 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:40: 24:46 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:23:46: 23:47 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:46: 24:47 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:23:48: 23:52 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:48: 24:52 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:23:52: 23:53 (#0), + span: $DIR/issue-75930-derive-cfg.rs:24:52: 24:53 (#0), }, Ident { ident: "third", - span: $DIR/issue-75930-derive-cfg.rs:24:5: 24:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:5: 25:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:24:10: 24:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:10: 25:11 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:24:13: 24:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:13: 25:15 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:16 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:15: 25:16 (#0), }, Group { delimiter: Brace, @@ -314,145 +314,145 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:9: 25:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:9: 26:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:25:15: 25:20 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:15: 26:20 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:21 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:14: 26:21 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:25:10: 25:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:22 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:25:23: 25:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:23: 26:29 (#0), }, Ident { ident: "Bar", - span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:30: 26:33 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:25:33: 25:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:26:33: 26:34 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:26:9: 26:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:9: 27:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:11: 27:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:26:15: 26:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:26:19: 26:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:19: 27:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:26:18: 26:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:18: 27:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:26:14: 26:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:14: 27:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:10: 27:27 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:26:28: 26:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:28: 27:34 (#0), }, Ident { ident: "Inner", - span: $DIR/issue-75930-derive-cfg.rs:26:35: 26:40 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:35: 27:40 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:26:40: 26:41 (#0), + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:41 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:27:9: 27:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:9: 28:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:27:11: 27:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:11: 28:14 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:20 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:20 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:27:14: 27:21 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:14: 28:21 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:27:10: 27:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:22 (#0), }, Ident { ident: "let", - span: $DIR/issue-75930-derive-cfg.rs:27:23: 27:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:23: 28:26 (#0), }, Ident { ident: "a", - span: $DIR/issue-75930-derive-cfg.rs:27:27: 27:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:27: 28:28 (#0), }, Punct { ch: '=', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:27:29: 27:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:29: 28:30 (#0), }, Literal { kind: Integer, symbol: "25", suffix: None, - span: $DIR/issue-75930-derive-cfg.rs:27:31: 27:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:31: 28:33 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:27:33: 27:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:28:33: 28:34 (#0), }, Ident { ident: "match", - span: $DIR/issue-75930-derive-cfg.rs:28:9: 28:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:9: 29:14 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:19 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:19 (#0), }, Group { delimiter: Brace, @@ -460,194 +460,194 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:29:13: 29:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:13: 30:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:29:19: 29:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:29:18: 29:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:29:14: 29:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:29:27: 29:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:27: 30:31 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:29:32: 29:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:32: 30:34 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:29:32: 29:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:32: 30:34 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:29:35: 29:37 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:37 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:29:37: 29:38 (#0), + span: $DIR/issue-75930-derive-cfg.rs:30:37: 30:38 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:30:13: 30:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:13: 31:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg_attr", - span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:30:24: 30:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:24: 31:27 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:28: 31:33 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:30:27: 30:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:27: 31:34 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:30:34: 30:35 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:34: 31:35 (#0), }, Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:30:36: 30:41 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:36: 31:41 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: $DIR/issue-75930-derive-cfg.rs:30:42: 30:50 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:42: 31:50 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:30:41: 30:51 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:41: 31:51 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:30:23: 30:52 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:23: 31:52 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:53 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:14: 31:53 (#0), }, Ident { ident: "false", - span: $DIR/issue-75930-derive-cfg.rs:30:54: 30:59 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:54: 31:59 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:30:60: 30:62 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:60: 31:62 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:30:60: 30:62 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:60: 31:62 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:30:63: 30:65 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:63: 31:65 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:30:65: 30:66 (#0), + span: $DIR/issue-75930-derive-cfg.rs:31:65: 31:66 (#0), }, Ident { ident: "_", - span: $DIR/issue-75930-derive-cfg.rs:31:13: 31:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:13: 32:14 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:17 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:17 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:17 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:31:18: 31:20 (#0), + span: $DIR/issue-75930-derive-cfg.rs:32:18: 32:20 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:28:20: 32:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:29:20: 33:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:32:10: 32:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:33:10: 33:11 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:34:9: 34:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:9: 35:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:34:11: 34:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:11: 35:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "should_be_removed", - span: $DIR/issue-75930-derive-cfg.rs:34:24: 34:41 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:24: 35:41 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:34:23: 34:42 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:23: 35:42 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:34:10: 34:43 (#0), + span: $DIR/issue-75930-derive-cfg.rs:35:10: 35:43 (#0), }, Ident { ident: "fn", - span: $DIR/issue-75930-derive-cfg.rs:35:9: 35:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:36:9: 36:11 (#0), }, Ident { ident: "removed_fn", - span: $DIR/issue-75930-derive-cfg.rs:35:12: 35:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:36:12: 36:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:35:22: 35:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:36:22: 36:24 (#0), }, Group { delimiter: Brace, @@ -655,108 +655,108 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:36:13: 36:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:13: 37:14 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:36:14: 36:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:14: 37:15 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:36:16: 36:19 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:16: 37:19 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:36:20: 36:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:20: 37:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:36:19: 36:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:19: 37:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:36:15: 36:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:37:15: 37:27 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:35:25: 37:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:36:25: 38:10 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:39:9: 39:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:9: 40:10 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:39:11: 39:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:11: 40:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "c", - span: $DIR/issue-75930-derive-cfg.rs:39:24: 39:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:24: 40:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:23: 39:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:23: 40:26 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:10: 39:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:10: 40:27 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:39:28: 39:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:28: 40:29 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:39:30: 39:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:30: 40:33 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:39:34: 39:37 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:34: 40:37 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:39:38: 39:43 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:38: 40:43 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:37: 39:44 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:37: 40:44 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:33: 39:45 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:33: 40:45 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:29: 39:46 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:29: 40:46 (#0), }, Ident { ident: "fn", - span: $DIR/issue-75930-derive-cfg.rs:39:47: 39:49 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:47: 40:49 (#0), }, Ident { ident: "kept_fn", - span: $DIR/issue-75930-derive-cfg.rs:39:50: 39:57 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:50: 40:57 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:39:57: 39:59 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:57: 40:59 (#0), }, Group { delimiter: Brace, @@ -764,82 +764,82 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:13: 41:14 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:40:14: 40:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:14: 41:15 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:40:16: 40:19 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:16: 41:19 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:40:20: 40:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:20: 41:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:40:24: 40:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:24: 41:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:40:23: 40:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:23: 41:30 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:40:19: 40:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:19: 41:31 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:40:15: 40:32 (#0), + span: $DIR/issue-75930-derive-cfg.rs:41:15: 41:32 (#0), }, Ident { ident: "let", - span: $DIR/issue-75930-derive-cfg.rs:41:13: 41:16 (#0), + span: $DIR/issue-75930-derive-cfg.rs:42:13: 42:16 (#0), }, Ident { ident: "my_val", - span: $DIR/issue-75930-derive-cfg.rs:41:17: 41:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:42:17: 42:23 (#0), }, Punct { ch: '=', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:41:24: 41:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:42:24: 42:25 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:41:26: 41:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:42:26: 42:30 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:41:30: 41:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:42:30: 42:31 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:39:60: 42:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:40:60: 43:10 (#0), }, Ident { ident: "enum", - span: $DIR/issue-75930-derive-cfg.rs:44:9: 44:13 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:9: 45:13 (#0), }, Ident { ident: "TupleEnum", - span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:14: 45:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), + span: $DIR/issue-75930-derive-cfg.rs:46:13: 46:16 (#0), }, Group { delimiter: Parenthesis, @@ -847,166 +847,166 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:46:17: 46:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:17: 47:18 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:46:19: 46:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:19: 47:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:46:23: 46:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:23: 47:28 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:46:22: 46:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:22: 47:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:46:18: 46:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:18: 47:30 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:46:31: 46:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:31: 47:33 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:46:33: 46:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:47:33: 47:34 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:47:17: 47:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:17: 48:18 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:47:19: 47:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:19: 48:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:47:23: 47:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:23: 48:28 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:47:22: 47:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:22: 48:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:47:18: 47:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:18: 48:30 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:47:31: 47:35 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:31: 48:35 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:47:35: 47:36 (#0), + span: $DIR/issue-75930-derive-cfg.rs:48:35: 48:36 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:48:17: 48:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:17: 49:18 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:48:19: 48:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:19: 49:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:48:23: 48:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:23: 49:26 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:48:27: 48:32 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:27: 49:32 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:48:26: 48:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:26: 49:33 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:48:22: 48:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:22: 49:34 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:48:18: 48:35 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:18: 49:35 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:48:36: 48:39 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:36: 49:39 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:48:39: 48:40 (#0), + span: $DIR/issue-75930-derive-cfg.rs:49:39: 49:40 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:49:17: 49:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:17: 50:18 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:49:19: 49:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:19: 50:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:49:23: 49:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:23: 50:28 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:49:22: 49:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:22: 50:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:49:18: 49:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:18: 50:30 (#0), }, Ident { ident: "String", - span: $DIR/issue-75930-derive-cfg.rs:49:31: 49:37 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:31: 50:37 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:49:37: 49:38 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:37: 50:38 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:49:39: 49:41 (#0), + span: $DIR/issue-75930-derive-cfg.rs:50:39: 50:41 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:45:16: 50:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:46:16: 51:14 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:44:24: 51:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:45:24: 52:10 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:53:9: 53:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:54:9: 54:15 (#0), }, Ident { ident: "TupleStruct", - span: $DIR/issue-75930-derive-cfg.rs:53:16: 53:27 (#0), + span: $DIR/issue-75930-derive-cfg.rs:54:16: 54:27 (#0), }, Group { delimiter: Parenthesis, @@ -1014,184 +1014,184 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:54:13: 54:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:13: 55:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:54:15: 54:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:15: 55:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:54:19: 54:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:19: 55:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:54:18: 54:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:18: 55:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:54:14: 54:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:14: 55:26 (#0), }, Ident { ident: "String", - span: $DIR/issue-75930-derive-cfg.rs:54:27: 54:33 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:27: 55:33 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:54:33: 54:34 (#0), + span: $DIR/issue-75930-derive-cfg.rs:55:33: 55:34 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:55:13: 55:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:13: 56:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:55:15: 55:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:15: 56:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:55:19: 55:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:19: 56:22 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:55:23: 55:28 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:23: 56:28 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:55:22: 55:29 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:22: 56:29 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:55:18: 55:30 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:18: 56:30 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:55:14: 55:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:14: 56:31 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:55:32: 55:35 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:32: 56:35 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:55:35: 55:36 (#0), + span: $DIR/issue-75930-derive-cfg.rs:56:35: 56:36 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:56:13: 56:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:13: 57:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:56:15: 56:18 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:15: 57:18 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:56:19: 56:24 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:19: 57:24 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:56:18: 56:25 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:18: 57:25 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:56:14: 56:26 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:14: 57:26 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:56:27: 56:31 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:27: 57:31 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:56:31: 56:32 (#0), + span: $DIR/issue-75930-derive-cfg.rs:57:31: 57:32 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:57:13: 57:15 (#0), + span: $DIR/issue-75930-derive-cfg.rs:58:13: 58:15 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:53:27: 58:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:54:27: 59:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:58:10: 58:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:59:10: 59:11 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/issue-75930-derive-cfg.rs:60:9: 60:10 (#0), + span: $DIR/issue-75930-derive-cfg.rs:61:9: 61:10 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:24:17: 61:6 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:17: 62:6 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:24:12: 61:7 (#0), + span: $DIR/issue-75930-derive-cfg.rs:25:12: 62:7 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:61:7: 61:8 (#0), + span: $DIR/issue-75930-derive-cfg.rs:62:7: 62:8 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:62:5: 62:6 (#0), + span: $DIR/issue-75930-derive-cfg.rs:63:5: 63:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:62:7: 62:19 (#0), + span: $DIR/issue-75930-derive-cfg.rs:63:7: 63:19 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "d", - span: $DIR/issue-75930-derive-cfg.rs:62:20: 62:21 (#0), + span: $DIR/issue-75930-derive-cfg.rs:63:20: 63:21 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:62:19: 62:22 (#0), + span: $DIR/issue-75930-derive-cfg.rs:63:19: 63:22 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:62:6: 62:23 (#0), + span: $DIR/issue-75930-derive-cfg.rs:63:6: 63:23 (#0), }, Ident { ident: "fourth", - span: $DIR/issue-75930-derive-cfg.rs:63:5: 63:11 (#0), + span: $DIR/issue-75930-derive-cfg.rs:64:5: 64:11 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:63:11: 63:12 (#0), + span: $DIR/issue-75930-derive-cfg.rs:64:11: 64:12 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:63:13: 63:14 (#0), + span: $DIR/issue-75930-derive-cfg.rs:64:13: 64:14 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:32: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:32: 65:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): #[allow(dead_code)] #[print_helper(b)] #[print_helper(a)] struct Foo < B > @@ -1211,141 +1211,141 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "dead_code", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "b", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "a", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '<', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "second", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "bool", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "third", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, @@ -1353,58 +1353,58 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "Inner", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "match", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, @@ -1412,146 +1412,146 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "false", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "_", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "c", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "fn", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "kept_fn", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, @@ -1559,82 +1559,82 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "let", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "my_val", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '=', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "true", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "enum", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "TupleEnum", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Foo", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, @@ -1642,69 +1642,69 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "struct", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "TupleStruct", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, @@ -1712,120 +1712,120 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "i32", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "u8", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: '#', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_helper", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "d", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "fourth", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Ident { ident: "B", - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ], - span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0), + span: $DIR/issue-75930-derive-cfg.rs:22:1: 65:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs index 6401522bdf89c..8d96381b9bdff 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.rs +++ b/src/test/ui/proc-macro/proc-macro-attributes.rs @@ -4,10 +4,18 @@ extern crate derive_b; #[B] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[C] //~ ERROR cannot find attribute `C` in this scope #[B(D)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[B(E = "foo")] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted #[derive(B)] struct B; diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr index 3ac93a748523a..1ba04258df0d5 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.stderr +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -1,5 +1,5 @@ error: cannot find attribute `C` in this scope - --> $DIR/proc-macro-attributes.rs:7:3 + --> $DIR/proc-macro-attributes.rs:9:3 | LL | #[C] | ^ help: a derive helper attribute with a similar name exists: `B` @@ -11,7 +11,7 @@ LL | #[B] | ^ ambiguous name | note: `B` could refer to the derive helper attribute defined here - --> $DIR/proc-macro-attributes.rs:11:10 + --> $DIR/proc-macro-attributes.rs:19:10 | LL | #[derive(B)] | ^ @@ -22,13 +22,13 @@ LL | #[macro_use] | ^^^^^^^^^^^^ error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) - --> $DIR/proc-macro-attributes.rs:8:3 + --> $DIR/proc-macro-attributes.rs:10:3 | LL | #[B(D)] | ^ ambiguous name | note: `B` could refer to the derive helper attribute defined here - --> $DIR/proc-macro-attributes.rs:11:10 + --> $DIR/proc-macro-attributes.rs:19:10 | LL | #[derive(B)] | ^ @@ -39,13 +39,13 @@ LL | #[macro_use] | ^^^^^^^^^^^^ error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) - --> $DIR/proc-macro-attributes.rs:9:3 + --> $DIR/proc-macro-attributes.rs:13:3 | LL | #[B(E = "foo")] | ^ ambiguous name | note: `B` could refer to the derive helper attribute defined here - --> $DIR/proc-macro-attributes.rs:11:10 + --> $DIR/proc-macro-attributes.rs:19:10 | LL | #[derive(B)] | ^ @@ -56,13 +56,13 @@ LL | #[macro_use] | ^^^^^^^^^^^^ error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) - --> $DIR/proc-macro-attributes.rs:10:3 + --> $DIR/proc-macro-attributes.rs:16:3 | LL | #[B(arbitrary tokens)] | ^ ambiguous name | note: `B` could refer to the derive helper attribute defined here - --> $DIR/proc-macro-attributes.rs:11:10 + --> $DIR/proc-macro-attributes.rs:19:10 | LL | #[derive(B)] | ^ @@ -72,6 +72,55 @@ note: `B` could also refer to the derive macro imported here LL | #[macro_use] | ^^^^^^^^^^^^ -error: aborting due to 5 previous errors +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:6:3 + | +LL | #[B] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = note: `#[warn(legacy_derive_helpers)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:10:3 + | +LL | #[B(D)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:13:3 + | +LL | #[B(E = "foo")] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B(arbitrary tokens)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +error: aborting due to 5 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs index 9f56eccb7a61c..c5e71a87dfbe8 100644 --- a/src/test/ui/proc-macro/reserved-macro-names.rs +++ b/src/test/ui/proc-macro/reserved-macro-names.rs @@ -17,9 +17,3 @@ pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { //~^ ERROR name `cfg_attr` is reserved in attribute namespace input } - -#[proc_macro_attribute] -pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream { - //~^ ERROR name `derive` is reserved in attribute namespace - input -} diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr index f871e43ce51df..39bdd03be863a 100644 --- a/src/test/ui/proc-macro/reserved-macro-names.stderr +++ b/src/test/ui/proc-macro/reserved-macro-names.stderr @@ -10,11 +10,5 @@ error: name `cfg_attr` is reserved in attribute namespace LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { | ^^^^^^^^ -error: name `derive` is reserved in attribute namespace - --> $DIR/reserved-macro-names.rs:22:8 - | -LL | pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream { - | ^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs index 8f1599a5abcb0..840c12e16e1c8 100644 --- a/src/test/ui/span/issue-43927-non-ADT-derive.rs +++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs @@ -1,10 +1,5 @@ -#![allow(dead_code)] - #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! -//~^ ERROR `derive` may only be applied to structs, enums and unions -//~| ERROR cannot determine resolution for the derive macro `Debug` -//~| ERROR cannot determine resolution for the derive macro `PartialEq` -//~| ERROR cannot determine resolution for the derive macro `Eq` +//~^ ERROR cannot determine resolution for the attribute macro `derive` struct DerivedOn; fn main() {} diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr index 85beac535c965..9ef81c5150a45 100644 --- a/src/test/ui/span/issue-43927-non-ADT-derive.stderr +++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr @@ -1,33 +1,10 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions - --> $DIR/issue-43927-non-ADT-derive.rs:3:1 +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/issue-43927-non-ADT-derive.rs:1:4 | LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug, PartialEq, Eq)]` - -error: cannot determine resolution for the derive macro `Debug` - --> $DIR/issue-43927-non-ADT-derive.rs:3:11 - | -LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the derive macro `PartialEq` - --> $DIR/issue-43927-non-ADT-derive.rs:3:18 - | -LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the derive macro `Eq` - --> $DIR/issue-43927-non-ADT-derive.rs:3:29 - | -LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^ + | ^^^^^^ | = note: import resolution is stuck, try simplifying macro imports -error: aborting due to 4 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0774`. diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs index 713b9eb542cfa..0a93105b66477 100644 --- a/src/test/ui/span/macro-ty-params.rs +++ b/src/test/ui/span/macro-ty-params.rs @@ -9,5 +9,5 @@ macro_rules! foo { () => () } fn main() { foo::!(); //~ ERROR generic arguments in macro path foo::<>!(); //~ ERROR generic arguments in macro path - m!(Default<>); //~ ERROR generic arguments in macro path + m!(Default<>); //~ ERROR unexpected generic arguments in path } diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr index 21683b2fb8643..138cd2598a1c5 100644 --- a/src/test/ui/span/macro-ty-params.stderr +++ b/src/test/ui/span/macro-ty-params.stderr @@ -10,7 +10,7 @@ error: generic arguments in macro path LL | foo::<>!(); | ^^ -error: generic arguments in macro path +error: unexpected generic arguments in path --> $DIR/macro-ty-params.rs:12:15 | LL | m!(Default<>); From f6caae52c1622a3c4f154eadaad615b577ceb6a8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 17 Jan 2021 16:05:02 +0300 Subject: [PATCH 2/3] Feature gate macro attributes in `#[derive]` output --- compiler/rustc_feature/src/active.rs | 4 ++ compiler/rustc_resolve/src/macros.rs | 30 ++++++++++ compiler/rustc_span/src/symbol.rs | 1 + .../attribute-after-derive-feature-gate.rs | 28 +++++++++ ...attribute-after-derive-feature-gate.stderr | 30 ++++++++++ .../ui/proc-macro/attribute-after-derive.rs | 2 + .../proc-macro/attribute-after-derive.stdout | 58 +++++++++---------- 7 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs create mode 100644 src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 4f38e06002367..2d0009c225c59 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -634,6 +634,10 @@ declare_features! ( /// Lessens the requirements for structs to implement `Unsize`. (active, relaxed_struct_unsize, "1.51.0", Some(1), None), + + /// Allows macro attributes to observe output of `#[derive]`. + (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6d3fde33f4d1e..f7010ca94bd2c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -280,6 +280,36 @@ impl<'a> ResolverExpand for Resolver<'a> { if let Res::Def(_, _) = res { let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod; self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); + + // Gate macro attributes in `#[derive]` output. + if !self.session.features_untracked().macro_attributes_in_derive_output + && kind == MacroKind::Attr + && ext.builtin_name != Some(sym::derive) + { + let mut expn_id = parent_scope.expansion; + loop { + // Helper attr table is a quick way to determine whether the attr is `derive`. + if self.helper_attrs.contains_key(&expn_id) { + feature_err( + &self.session.parse_sess, + sym::macro_attributes_in_derive_output, + path.span, + "macro attributes in `#[derive]` output are unstable", + ) + .emit(); + break; + } else { + let expn_data = expn_id.expn_data(); + match expn_data.kind { + ExpnKind::Root + | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => { + break; + } + _ => expn_id = expn_data.parent, + } + } + } + } } Ok(ext) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 86f8061a24aff..20e4f7262acb9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -679,6 +679,7 @@ symbols! { loop_break_value, lt, macro_at_most_once_rep, + macro_attributes_in_derive_output, macro_escape, macro_export, macro_lifetime_matcher, diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs new file mode 100644 index 0000000000000..74751a23d7983 --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs @@ -0,0 +1,28 @@ +// gate-test-macro_attributes_in_derive_output +// aux-build: test-macros.rs + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] +#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable +struct S1 { + field: [u8; 10], +} + +#[derive(Empty)] +#[empty_helper] +#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable +struct S2 { + field: [u8; 10], +} + +#[derive(Empty)] +struct S3 { + field: [u8; #[identity_attr] 10], //~ ERROR macro attributes in `#[derive]` output are unstable +} + +fn main() {} diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr new file mode 100644 index 0000000000000..74cace628b94c --- /dev/null +++ b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr @@ -0,0 +1,30 @@ +error[E0658]: macro attributes in `#[derive]` output are unstable + --> $DIR/attribute-after-derive-feature-gate.rs:11:3 + | +LL | #[empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #81119 for more information + = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable + +error[E0658]: macro attributes in `#[derive]` output are unstable + --> $DIR/attribute-after-derive-feature-gate.rs:18:3 + | +LL | #[empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #81119 for more information + = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable + +error[E0658]: macro attributes in `#[derive]` output are unstable + --> $DIR/attribute-after-derive-feature-gate.rs:25:19 + | +LL | field: [u8; #[identity_attr] 10], + | ^^^^^^^^^^^^^ + | + = note: see issue #81119 for more information + = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs index 0f0f27bff97be..ac3f28b6ef3ea 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.rs +++ b/src/test/ui/proc-macro/attribute-after-derive.rs @@ -5,6 +5,8 @@ // compile-flags: -Z span-debug // aux-build: test-macros.rs +#![feature(macro_attributes_in_derive_output)] + #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout index 78c58c0a32fcf..11f492353271a 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.stdout +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -3,35 +3,35 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0), + span: $DIR/attribute-after-derive.rs:17:1: 17:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "derive", - span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0), + span: $DIR/attribute-after-derive.rs:17:3: 17:9 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "Print", - span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0), + span: $DIR/attribute-after-derive.rs:17:10: 17:15 (#0), }, ], - span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0), + span: $DIR/attribute-after-derive.rs:17:9: 17:16 (#0), }, ], - span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0), + span: $DIR/attribute-after-derive.rs:17:2: 17:17 (#0), }, Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0), }, Ident { ident: "AttributeDerive", - span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0), }, Group { delimiter: Brace, @@ -39,80 +39,80 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0), + span: $DIR/attribute-after-derive.rs:19:5: 19:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0), + span: $DIR/attribute-after-derive.rs:19:7: 19:10 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), + span: $DIR/attribute-after-derive.rs:19:11: 19:16 (#0), }, ], - span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0), + span: $DIR/attribute-after-derive.rs:19:10: 19:17 (#0), }, ], - span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0), + span: $DIR/attribute-after-derive.rs:19:6: 19:18 (#0), }, Ident { ident: "field", - span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0), + span: $DIR/attribute-after-derive.rs:20:5: 20:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0), + span: $DIR/attribute-after-derive.rs:20:10: 20:11 (#0), }, Ident { ident: "u8", - span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0), + span: $DIR/attribute-after-derive.rs:20:12: 20:14 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0), + span: $DIR/attribute-after-derive.rs:20:14: 20:15 (#0), }, ], - span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), }, Ident { ident: "AttributeDerive", - span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:16:1: 19:2 (#0), + span: $DIR/attribute-after-derive.rs:18:1: 21:2 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Ident { ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { } @@ -120,29 +120,29 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_attr", - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, ], - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Ident { ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:23:1: 26:2 (#0), + span: $DIR/attribute-after-derive.rs:25:1: 28:2 (#0), }, ] From d8af6de911957075ca6e0e51b034513b51849d99 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 7 Feb 2021 19:26:33 +0300 Subject: [PATCH 3/3] Address review comments --- compiler/rustc_expand/src/base.rs | 3 +++ src/test/ui/derives/derive-renamed.rs | 11 ++++++++++ .../attribute-after-derive-feature-gate.rs | 9 ++++++++ .../proc-macro/derive-helper-legacy-limits.rs | 21 +++++++++++++++++++ .../derive-helper-legacy-limits.stderr | 8 +++++++ 5 files changed, 52 insertions(+) create mode 100644 src/test/ui/derives/derive-renamed.rs create mode 100644 src/test/ui/proc-macro/derive-helper-legacy-limits.rs create mode 100644 src/test/ui/proc-macro/derive-helper-legacy-limits.stderr diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 35ddb1fb9bc51..196a774355e10 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -141,6 +141,9 @@ impl Annotatable { } crate fn into_tokens(self, sess: &ParseSess) -> TokenStream { + // Tokens of an attribute target may be invalidated by some outer `#[derive]` performing + // "full configuration" (attributes following derives on the same item should be the most + // common case), that's why synthesizing tokens is allowed. nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::Yes) } diff --git a/src/test/ui/derives/derive-renamed.rs b/src/test/ui/derives/derive-renamed.rs new file mode 100644 index 0000000000000..d310e5806c560 --- /dev/null +++ b/src/test/ui/derives/derive-renamed.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2018 + +use derive as my_derive; + +#[my_derive(Debug)] +struct S; + +fn main() { + println!("{:?}", S); // OK +} diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs index 74751a23d7983..f0fec6782423e 100644 --- a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs +++ b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs @@ -25,4 +25,13 @@ struct S3 { field: [u8; #[identity_attr] 10], //~ ERROR macro attributes in `#[derive]` output are unstable } +#[derive(Empty)] +struct S4 { + field: [u8; { + #[derive(Empty)] // OK, not gated + struct Inner; + 10 + }] +} + fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.rs b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs new file mode 100644 index 0000000000000..ca904900da0bb --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs @@ -0,0 +1,21 @@ +// Support for legacy derive helpers is limited and heuristic-based +// (that's exactly the reason why they are deprecated). + +// edition:2018 +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +use derive as my_derive; + +#[my_derive(Empty)] +#[empty_helper] // OK +struct S1; + +// Legacy helper detection doesn't see through `derive` renaming. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[my_derive(Empty)] +struct S2; + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr new file mode 100644 index 0000000000000..186f38a00f917 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-legacy-limits.rs:17:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error: aborting due to previous error +