From c064630e77a9e14040176aa8e8eea67f7adcc643 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 4 Oct 2019 01:44:57 +0300 Subject: [PATCH 1/4] resolve: `Scope::DeriveHelpers` -> `Scope::DeriveHelpersCompat` These helpers are resolved before their respective derives through a kind of look ahead into future expansions. Some of these will migrate to proper resolution, others will be deprecated. ``` #[trait_helper] // Deprecate #[derive(Trait)] #[trait_helper] // Migrate to proper resolution ``` --- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_resolve/macros.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1ebe9b5e120f4..4efbc5a6405d2 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -368,7 +368,7 @@ impl<'a> Resolver<'a> { let mut suggestions = Vec::new(); self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| { match scope { - Scope::DeriveHelpers => { + Scope::DeriveHelpersCompat => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { for derive in parent_scope.derives { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 47e8cf80a05bf..2779924d485a2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -97,7 +97,7 @@ impl Determinacy { /// but not for late resolution yet. #[derive(Clone, Copy)] enum Scope<'a> { - DeriveHelpers, + DeriveHelpersCompat, MacroRules(LegacyScope<'a>), CrateRoot, Module(Module<'a>), @@ -1477,14 +1477,14 @@ impl<'a> Resolver<'a> { let mut scope = match ns { _ if is_absolute_path => Scope::CrateRoot, TypeNS | ValueNS => Scope::Module(module), - MacroNS => Scope::DeriveHelpers, + MacroNS => Scope::DeriveHelpersCompat, }; let mut ident = ident.modern(); let mut use_prelude = !module.no_implicit_prelude; loop { let visit = match scope { - Scope::DeriveHelpers => true, + Scope::DeriveHelpersCompat => true, Scope::MacroRules(..) => true, Scope::CrateRoot => true, Scope::Module(..) => true, @@ -1505,7 +1505,7 @@ impl<'a> Resolver<'a> { } scope = match scope { - Scope::DeriveHelpers => + Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy), Scope::MacroRules(legacy_scope) => match legacy_scope { LegacyScope::Binding(binding) => Scope::MacroRules( diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2d125a459c86b..0d6dd5a7f105c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -498,7 +498,7 @@ impl<'a> Resolver<'a> { Flags::empty(), )); let result = match scope { - Scope::DeriveHelpers => { + Scope::DeriveHelpersCompat => { let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; From a3126a5013e851354f5c10efe3c166332a0a9b46 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 4 Oct 2019 01:53:20 +0300 Subject: [PATCH 2/4] resolve: Introduce a new scope for derive helpers --- src/librustc_resolve/diagnostics.rs | 9 ++++++ src/librustc_resolve/lib.rs | 30 +++++++++++++++---- src/librustc_resolve/macros.rs | 22 +++++++++++++- .../ui/proc-macro/derive-helper-shadowing.rs | 4 +-- .../proc-macro/derive-helper-shadowing.stderr | 26 +++++++++++++--- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 4efbc5a6405d2..f2858a6215642 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -368,6 +368,15 @@ impl<'a> Resolver<'a> { let mut suggestions = Vec::new(); self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| { match scope { + Scope::DeriveHelpers(expn_id) => { + let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); + if filter_fn(res) { + suggestions.extend(this.helper_attrs.get(&expn_id) + .into_iter().flatten().map(|ident| { + TypoSuggestion::from_res(ident.name, res) + })); + } + } Scope::DeriveHelpersCompat => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2779924d485a2..0f410c623bafa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -45,7 +45,7 @@ use syntax::symbol::{kw, sym}; use syntax::source_map::Spanned; use syntax::visit::{self, Visitor}; use syntax_expand::base::SyntaxExtension; -use syntax_pos::hygiene::{MacroKind, ExpnId, Transparency, SyntaxContext}; +use syntax_pos::hygiene::{MacroKind, ExpnId, ExpnKind, Transparency, SyntaxContext}; use syntax_pos::{Span, DUMMY_SP}; use errors::{Applicability, DiagnosticBuilder}; @@ -97,6 +97,7 @@ impl Determinacy { /// but not for late resolution yet. #[derive(Clone, Copy)] enum Scope<'a> { + DeriveHelpers(ExpnId), DeriveHelpersCompat, MacroRules(LegacyScope<'a>), CrateRoot, @@ -942,6 +943,8 @@ pub struct Resolver<'a> { /// Legacy scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. output_legacy_scopes: FxHashMap>, + /// Helper attributes that are in scope for the given expansion. + helper_attrs: FxHashMap>, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, @@ -1219,6 +1222,7 @@ impl<'a> Resolver<'a> { non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], invocation_parent_scopes, output_legacy_scopes: Default::default(), + helper_attrs: Default::default(), macro_defs, local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), @@ -1467,23 +1471,26 @@ impl<'a> Resolver<'a> { // in prelude, not sure where exactly (creates ambiguities with any other prelude names). let rust_2015 = ident.span.rust_2015(); - let (ns, is_absolute_path) = match scope_set { - ScopeSet::All(ns, _) => (ns, false), - ScopeSet::AbsolutePath(ns) => (ns, true), - ScopeSet::Macro(_) => (MacroNS, false), + let (ns, macro_kind, is_absolute_path) = match scope_set { + ScopeSet::All(ns, _) => (ns, None, false), + ScopeSet::AbsolutePath(ns) => (ns, None, true), + ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), }; // Jump out of trait or enum modules, they do not act as scopes. let module = parent_scope.module.nearest_item_scope(); let mut scope = match ns { _ if is_absolute_path => Scope::CrateRoot, TypeNS | ValueNS => Scope::Module(module), - MacroNS => Scope::DeriveHelpersCompat, + MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ident = ident.modern(); let mut use_prelude = !module.no_implicit_prelude; loop { let visit = match scope { + // Derive helpers are not in scope when resolving derives in the same container. + Scope::DeriveHelpers(expn_id) => + !(expn_id == parent_scope.expansion && macro_kind == Some(MacroKind::Derive)), Scope::DeriveHelpersCompat => true, Scope::MacroRules(..) => true, Scope::CrateRoot => true, @@ -1505,6 +1512,17 @@ impl<'a> Resolver<'a> { } scope = match scope { + Scope::DeriveHelpers(expn_id) if expn_id != ExpnId::root() => { + // Derive helpers are not visible to code generated by bang or derive macros. + let expn_data = expn_id.expn_data(); + match expn_data.kind { + ExpnKind::Root | + ExpnKind::Macro(MacroKind::Bang, _) | + ExpnKind::Macro(MacroKind::Derive, _) => Scope::DeriveHelpersCompat, + _ => Scope::DeriveHelpers(expn_data.parent), + } + } + Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat, Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy), Scope::MacroRules(legacy_scope) => match legacy_scope { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0d6dd5a7f105c..c1d0abece4233 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -237,15 +237,23 @@ impl<'a> base::Resolver for Resolver<'a> { // - 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), _)) => ext, + Ok((Some(ext), _)) => { + let span = path.segments.last().unwrap().ident.span.modern(); + helper_attrs.extend( + ext.helper_attrs.iter().map(|name| Ident::new(*name, span)) + ); + 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)); } }; @@ -498,6 +506,18 @@ impl<'a> Resolver<'a> { Flags::empty(), )); let result = match scope { + Scope::DeriveHelpers(expn_id) => { + if let Some(attr) = this.helper_attrs.get(&expn_id).and_then(|attrs| { + attrs.iter().rfind(|i| ident == **i) + }) { + let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, attr.span, expn_id) + .to_name_binding(this.arenas); + Ok((binding, Flags::empty())) + } else { + Err(Determinacy::Determined) + } + } Scope::DeriveHelpersCompat => { let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index 21af4093a037d..a8f4eea4cb70b 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -1,3 +1,4 @@ +// edition:2018 // aux-build:test-macros.rs #[macro_use] @@ -11,8 +12,7 @@ struct S { // FIXME No ambiguity, attributes in non-macro positions are not resolved properly #[empty_helper] field: [u8; { - // FIXME No ambiguity, derive helpers are not put into scope for non-attributes - use empty_helper; + use empty_helper; //~ ERROR `empty_helper` is ambiguous // FIXME No ambiguity, derive helpers are not put into scope for inner items #[empty_helper] diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 2ba517ce29ee7..ca9d6125e4bfa 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,21 +1,39 @@ +error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution) + --> $DIR/derive-helper-shadowing.rs:15:13 + | +LL | use empty_helper; + | ^^^^^^^^^^^^ ambiguous name + | +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:10:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:7:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:8:3 + --> $DIR/derive-helper-shadowing.rs:9:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:9:10 + --> $DIR/derive-helper-shadowing.rs:10:10 | LL | #[derive(Empty)] | ^^^^^ note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:6:5 + --> $DIR/derive-helper-shadowing.rs:7:5 | 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 +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. From 808522894b612bca8273f20ba4cfa328622c5a97 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 5 Oct 2019 16:30:08 +0300 Subject: [PATCH 3/4] expand: Stop marking derive helper attributes as known Pass them through name resolution instead --- src/librustc_resolve/macros.rs | 3 ++ src/libsyntax_expand/expand.rs | 20 ++-------- src/libsyntax_expand/proc_macro.rs | 19 +-------- .../ui/proc-macro/derive-helper-shadowing.rs | 8 ++-- .../proc-macro/derive-helper-shadowing.stderr | 40 ++++++++++++++++++- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c1d0abece4233..cf549d5ba6f70 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -247,6 +247,9 @@ impl<'a> base::Resolver for Resolver<'a> { helper_attrs.extend( ext.helper_attrs.iter().map(|name| Ident::new(*name, span)) ); + if ext.is_derive_copy { + self.add_derive_copy(invoc_id); + } ext } Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index b7f6364c2b55c..06aa5deb6e018 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -1,5 +1,5 @@ use crate::base::*; -use crate::proc_macro::{collect_derives, MarkAttrs}; +use crate::proc_macro::collect_derives; use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; use crate::mbe::macro_rules::annotate_err_with_kind; use crate::placeholders::{placeholder, PlaceholderExpander}; @@ -394,7 +394,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let fragment = self.expand_invoc(invoc, &ext.kind); self.collect_invocations(fragment, &[]) } - InvocationRes::DeriveContainer(exts) => { + InvocationRes::DeriveContainer(_exts) => { + // FIXME: Consider using the derive resolutions (`_exts`) immediately, + // instead of enqueuing the derives to be resolved again later. let (derives, item) = match invoc.kind { InvocationKind::DeriveContainer { derives, item } => (derives, item), _ => unreachable!(), @@ -421,20 +423,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive))); - let mut helper_attrs = Vec::new(); - let mut has_copy = false; - for ext in exts { - helper_attrs.extend(&ext.helper_attrs); - has_copy |= ext.is_derive_copy; - } - // Mark derive helpers inside this item as known and used. - // FIXME: This is a hack, derive helpers should be integrated with regular name - // resolution instead. For example, helpers introduced by a derive container - // can be in scope for all code produced by that container's expansion. - item.visit_with(&mut MarkAttrs(&helper_attrs)); - if has_copy { - self.cx.resolver.add_derive_copy(invoc.expansion_data.id); - } let mut derive_placeholders = Vec::with_capacity(derives.len()); invocations.reserve(derives.len()); diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs index db981fae5c224..099cf0a4be904 100644 --- a/src/libsyntax_expand/proc_macro.rs +++ b/src/libsyntax_expand/proc_macro.rs @@ -1,13 +1,11 @@ use crate::base::{self, *}; use crate::proc_macro_server; -use syntax::ast::{self, ItemKind, Attribute, Mac}; -use syntax::attr::{mark_used, mark_known}; +use syntax::ast::{self, ItemKind}; use syntax::errors::{Applicability, FatalError}; use syntax::symbol::sym; use syntax::token; use syntax::tokenstream::{self, TokenStream}; -use syntax::visit::Visitor; use rustc_data_structures::sync::Lrc; use syntax_pos::{Span, DUMMY_SP}; @@ -167,21 +165,6 @@ impl MultiItemModifier for ProcMacroDerive { } } -crate struct MarkAttrs<'a>(crate &'a [ast::Name]); - -impl<'a> Visitor<'a> for MarkAttrs<'a> { - fn visit_attribute(&mut self, attr: &Attribute) { - if let Some(ident) = attr.ident() { - if self.0.contains(&ident.name) { - mark_used(attr); - mark_known(attr); - } - } - } - - fn visit_mac(&mut self, _mac: &Mac) {} -} - crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) -> Vec { let mut result = Vec::new(); attrs.retain(|attr| { diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index a8f4eea4cb70b..fe324ae63cd33 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -9,17 +9,15 @@ use test_macros::empty_attr as empty_helper; #[empty_helper] //~ ERROR `empty_helper` is ambiguous #[derive(Empty)] struct S { - // FIXME No ambiguity, attributes in non-macro positions are not resolved properly - #[empty_helper] + #[empty_helper] //~ ERROR `empty_helper` is ambiguous field: [u8; { use empty_helper; //~ ERROR `empty_helper` is ambiguous - // FIXME No ambiguity, derive helpers are not put into scope for inner items - #[empty_helper] + #[empty_helper] //~ ERROR `empty_helper` is ambiguous struct U; mod inner { - // FIXME No ambiguity, attributes in non-macro positions are not resolved properly + // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper. #[empty_helper] struct V; } diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index ca9d6125e4bfa..66ce34799da89 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,5 +1,5 @@ error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution) - --> $DIR/derive-helper-shadowing.rs:15:13 + --> $DIR/derive-helper-shadowing.rs:14:13 | LL | use empty_helper; | ^^^^^^^^^^^^ ambiguous name @@ -34,6 +34,42 @@ 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 2 previous errors +error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) + --> $DIR/derive-helper-shadowing.rs:12:7 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:10:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:7:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) + --> $DIR/derive-helper-shadowing.rs:16:11 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:10:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:7:5 + | +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 4 previous errors For more information about this error, try `rustc --explain E0659`. From 8668c1a19015148821c37255922f9a9b603dd148 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 5 Oct 2019 16:59:52 +0300 Subject: [PATCH 4/4] Add some more tests --- .../auxiliary/derive-helper-shadowing.rs | 15 ++++++ .../ui/proc-macro/derive-helper-shadowing.rs | 23 ++++++++ .../proc-macro/derive-helper-shadowing.stderr | 53 ++++++++++++++----- 3 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs new file mode 100644 index 0000000000000..41d3a184640ac --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(GenHelperUse)] +pub fn derive_a(_: TokenStream) -> TokenStream { + " + #[empty_helper] + struct Uwu; + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index fe324ae63cd33..f0ca34db414d4 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -1,11 +1,21 @@ // edition:2018 // aux-build:test-macros.rs +// aux-build:derive-helper-shadowing.rs #[macro_use] extern crate test_macros; +#[macro_use] +extern crate derive_helper_shadowing; use test_macros::empty_attr as empty_helper; +macro_rules! gen_helper_use { + () => { + #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope + struct W; + } +} + #[empty_helper] //~ ERROR `empty_helper` is ambiguous #[derive(Empty)] struct S { @@ -20,12 +30,25 @@ struct S { // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper. #[empty_helper] struct V; + + gen_helper_use!(); + + #[derive(GenHelperUse)] //~ ERROR cannot find attribute `empty_helper` in this scope + struct Owo; + + use empty_helper as renamed; + #[renamed] //~ ERROR cannot use a derive helper attribute through an import + struct Wow; } 0 }] } +// OK, no ambiguity, only the non-helper attribute is in scope. +#[empty_helper] +struct Z; + fn main() { let s = S { field: [] }; } diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 66ce34799da89..9048830bee24d 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,75 +1,102 @@ +error: cannot use a derive helper attribute through an import + --> $DIR/derive-helper-shadowing.rs:40:15 + | +LL | #[renamed] + | ^^^^^^^ + | +note: the derive helper attribute imported here + --> $DIR/derive-helper-shadowing.rs:39:17 + | +LL | use empty_helper as renamed; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:36:22 + | +LL | #[derive(GenHelperUse)] + | ^^^^^^^^^^^^ + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:14:11 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | gen_helper_use!(); + | ------------------ in this macro invocation + error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution) - --> $DIR/derive-helper-shadowing.rs:14:13 + --> $DIR/derive-helper-shadowing.rs:24:13 | LL | use empty_helper; | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:10:10 + --> $DIR/derive-helper-shadowing.rs:20:10 | LL | #[derive(Empty)] | ^^^^^ note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:7:5 + --> $DIR/derive-helper-shadowing.rs:10:5 | LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:9:3 + --> $DIR/derive-helper-shadowing.rs:19:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:10:10 + --> $DIR/derive-helper-shadowing.rs:20:10 | LL | #[derive(Empty)] | ^^^^^ note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:7:5 + --> $DIR/derive-helper-shadowing.rs:10:5 | LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:12:7 + --> $DIR/derive-helper-shadowing.rs:22:7 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:10:10 + --> $DIR/derive-helper-shadowing.rs:20:10 | LL | #[derive(Empty)] | ^^^^^ note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:7:5 + --> $DIR/derive-helper-shadowing.rs:10:5 | LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:16:11 + --> $DIR/derive-helper-shadowing.rs:26:11 | LL | #[empty_helper] | ^^^^^^^^^^^^ ambiguous name | note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:10:10 + --> $DIR/derive-helper-shadowing.rs:20:10 | LL | #[derive(Empty)] | ^^^^^ note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:7:5 + --> $DIR/derive-helper-shadowing.rs:10:5 | 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 4 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0659`.