diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 35d96b9302b43..89bc2f2709a3c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -575,6 +575,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 5. Standard library prelude (de-facto closed, controlled). // 6. Language prelude (closed, controlled). // (Macro NS) + // 0. Derive helpers (open, not controlled). All ambiguities with other names + // are currently reported as errors. They should be higher in priority than preludes + // and probably even names in modules according to the "general principles" above. They + // also should be subject to restricted shadowing because are effectively produced by + // derives (you need to resolve the derive first to add helpers into scope), but they + // should be available before the derive is expanded for compatibility. + // It's mess in general, so we are being conservative for now. // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents // (open, not controlled). // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled). @@ -583,13 +590,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins). // 4. Language prelude: builtin attributes (closed, controlled). - // N (unordered). Derive helpers (open, not controlled). All ambiguities with other names - // are currently reported as errors. They should be higher in priority than preludes - // and maybe even names in modules according to the "general principles" above. They - // also should be subject to restricted shadowing because are effectively produced by - // derives (you need to resolve the derive first to add helpers into scope), but they - // should be available before the derive is expanded for compatibility. - // It's mess in general, so we are being conservative for now. assert!(ns == TypeNS || ns == MacroNS); assert!(force || !record_used); // `record_used` implies `force` @@ -621,7 +621,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } // Go through all the scopes and try to resolve the name. - let mut where_to_resolve = WhereToResolve::Module(parent_scope.module); + let mut where_to_resolve = WhereToResolve::DeriveHelpers; let mut use_prelude = !parent_scope.module.no_implicit_prelude; loop { let result = match where_to_resolve { @@ -751,8 +751,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros, WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, - WhereToResolve::BuiltinAttrs => WhereToResolve::DeriveHelpers, - WhereToResolve::DeriveHelpers => break, // nowhere else to search + WhereToResolve::BuiltinAttrs => break, // nowhere else to search + WhereToResolve::DeriveHelpers => WhereToResolve::Module(parent_scope.module), WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes, diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs index 83bbb7c13c43f..d0aed8b162486 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs @@ -11,13 +11,11 @@ // aux-build:derive-b.rs // ignore-stage1 -#![allow(warnings)] - #[macro_use] extern crate derive_b; -#[B] //~ ERROR `B` is a derive mode -#[C] +#[B] +#[C] //~ ERROR attribute `C` is currently unknown to the compiler #[B(D)] #[B(E = "foo")] #[B(arbitrary tokens)] diff --git a/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs b/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs index 7be909c3c9e87..124bc05b7a348 100644 --- a/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs +++ b/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs @@ -25,3 +25,13 @@ pub fn derive_foo(input: TokenStream) -> TokenStream { pub fn derive_bar(input: TokenStream) -> TokenStream { panic!("lolnope"); } + +#[proc_macro_derive(WithHelper, attributes(helper))] +pub fn with_helper(input: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn helper(_: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs new file mode 100644 index 0000000000000..b750a8bb0d932 --- /dev/null +++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs @@ -0,0 +1,13 @@ +// aux-build:plugin.rs +// ignore-stage1 + +#[macro_use(WithHelper)] +extern crate plugin; + +use plugin::helper; + +#[derive(WithHelper)] +#[helper] //~ ERROR `helper` is ambiguous +struct S; + +fn main() {} diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr new file mode 100644 index 0000000000000..059629c0b62d5 --- /dev/null +++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr @@ -0,0 +1,20 @@ +error[E0659]: `helper` is ambiguous + --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:3 + | +LL | #[helper] //~ ERROR `helper` is ambiguous + | ^^^^^^ ambiguous name + | +note: `helper` could refer to the name defined here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:9:10 + | +LL | #[derive(WithHelper)] + | ^^^^^^^^^^ +note: `helper` could also refer to the name imported here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:5 + | +LL | use plugin::helper; + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs new file mode 100644 index 0000000000000..03b774f6c6400 --- /dev/null +++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs @@ -0,0 +1,29 @@ +// compile-pass +// aux-build:plugin.rs +// ignore-stage1 + +#[macro_use(WithHelper)] +extern crate plugin; + +use self::one::*; +use self::two::*; + +mod helper {} + +mod one { + use helper; + + #[derive(WithHelper)] + #[helper] + struct One; +} + +mod two { + use helper; + + #[derive(WithHelper)] + #[helper] + struct Two; +} + +fn main() {} diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr index cdfecb3d10146..e0aeae4ba6c54 100644 --- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr @@ -4,17 +4,16 @@ error[E0659]: `my_attr` is ambiguous LL | #[my_attr] //~ ERROR `my_attr` is ambiguous | ^^^^^^^ ambiguous name | -note: `my_attr` could refer to the name imported here - --> $DIR/derive-helper-shadowing.rs:4:5 - | -LL | use derive_helper_shadowing::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: `my_attr` could also refer to the name defined here +note: `my_attr` could refer to the name defined here --> $DIR/derive-helper-shadowing.rs:7:10 | LL | #[derive(MyTrait)] | ^^^^^^^ - = note: consider adding an explicit import of `my_attr` to disambiguate +note: `my_attr` could also refer to the name imported here + --> $DIR/derive-helper-shadowing.rs:4:5 + | +LL | use derive_helper_shadowing::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error