diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 7c10292061f75..7a26a239aeffa 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -129,6 +129,16 @@ pub enum Namespace { MacroNS, } +impl Namespace { + pub fn descr(self) -> &'static str { + match self { + TypeNS => "type", + ValueNS => "value", + MacroNS => "macro", + } + } +} + /// Just a helper ‒ separate structure for each namespace. #[derive(Copy, Clone, Default, Debug)] pub struct PerNS { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 328cb8225478b..49a4a1b78a1a8 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -153,6 +153,7 @@ impl Decodable for DefPathTable { /// The definition table containing node definitions. /// It holds the DefPathTable for local DefIds/DefPaths and it also stores a /// mapping from NodeIds to local DefIds. +#[derive(Clone)] pub struct Definitions { table: DefPathTable, node_to_def_index: NodeMap, @@ -161,34 +162,12 @@ pub struct Definitions { /// If `Mark` is an ID of some macro expansion, /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. parent_modules_of_macro_defs: FxHashMap, - /// Item with a given `DefIndex` was defined during opaque macro expansion with ID `Mark`. - /// It can actually be defined during transparent macro expansions inside that opaque expansion, - /// but transparent expansions are ignored here. - opaque_expansions_that_defined: FxHashMap, + /// Item with a given `DefIndex` was defined during macro expansion with ID `Mark`. + expansions_that_defined: FxHashMap, next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>, def_index_to_span: FxHashMap, } -// Unfortunately we have to provide a manual impl of Clone because of the -// fixed-sized array field. -impl Clone for Definitions { - fn clone(&self) -> Self { - Definitions { - table: self.table.clone(), - node_to_def_index: self.node_to_def_index.clone(), - def_index_to_node: [ - self.def_index_to_node[0].clone(), - self.def_index_to_node[1].clone(), - ], - node_to_hir_id: self.node_to_hir_id.clone(), - parent_modules_of_macro_defs: self.parent_modules_of_macro_defs.clone(), - opaque_expansions_that_defined: self.opaque_expansions_that_defined.clone(), - next_disambiguator: self.next_disambiguator.clone(), - def_index_to_span: self.def_index_to_span.clone(), - } - } -} - /// A unique identifier that we can use to lookup a definition /// precisely. It combines the index of the definition's parent (if /// any) with a `DisambiguatedDefPathData`. @@ -409,7 +388,7 @@ impl Definitions { def_index_to_node: [vec![], vec![]], node_to_hir_id: IndexVec::new(), parent_modules_of_macro_defs: FxHashMap(), - opaque_expansions_that_defined: FxHashMap(), + expansions_that_defined: FxHashMap(), next_disambiguator: FxHashMap(), def_index_to_span: FxHashMap(), } @@ -584,9 +563,8 @@ impl Definitions { self.node_to_def_index.insert(node_id, index); } - let expansion = expansion.modern(); if expansion != Mark::root() { - self.opaque_expansions_that_defined.insert(index, expansion); + self.expansions_that_defined.insert(index, expansion); } // The span is added if it isn't dummy @@ -606,8 +584,8 @@ impl Definitions { self.node_to_hir_id = mapping; } - pub fn opaque_expansion_that_defined(&self, index: DefIndex) -> Mark { - self.opaque_expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root()) + pub fn expansion_that_defined(&self, index: DefIndex) -> Mark { + self.expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root()) } pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId { diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index a6bbd93750575..efc2d9311c1dc 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -316,6 +316,12 @@ declare_lint! { "checks the object safety of where clauses" } +declare_lint! { + pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + Warn, + "detects proc macro derives using inaccessible names from parent modules" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -372,6 +378,7 @@ impl LintPass for HardwiredLints { DUPLICATE_MACRO_EXPORTS, INTRA_DOC_LINK_RESOLUTION_FAILURE, WHERE_CLAUSES_OBJECT_SAFETY, + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, ) } } @@ -384,6 +391,7 @@ pub enum BuiltinLintDiagnostics { BareTraitObject(Span, /* is_global */ bool), AbsPathWithModule(Span), DuplicatedMacroExports(ast::Ident, Span, Span), + ProcMacroDeriveResolutionFallback(Span), } impl BuiltinLintDiagnostics { @@ -420,6 +428,10 @@ impl BuiltinLintDiagnostics { db.span_label(later_span, format!("`{}` already exported", ident)); db.span_note(earlier_span, "previous macro export is now shadowed"); } + BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => { + db.span_label(span, "names from parent modules are not \ + accessible without an explicit import"); + } } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 98042f6389db6..4a76cc683f680 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2724,7 +2724,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) { ident = ident.modern(); let target_expansion = match scope.krate { - LOCAL_CRATE => self.hir.definitions().opaque_expansion_that_defined(scope.index), + LOCAL_CRATE => self.hir.definitions().expansion_that_defined(scope.index), _ => Mark::root(), }; let scope = match ident.span.adjust(target_expansion) { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index adc700506ffc0..27e51ad8961df 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -293,6 +293,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #50589 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK), + reference: "issue #50504 ", + edition: None, + }, ]); // Register renamed and removed lints diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e8dcfc027ef8b..ad63a43fead5c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -55,7 +55,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; use syntax::attr; -use syntax::ast::{Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind}; +use syntax::ast::{CRATE_NODE_ID, Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind}; use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; @@ -1891,7 +1891,12 @@ impl<'a> Resolver<'a> { ident.span = ident.span.modern(); loop { - module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break); + let (opt_module, poisoned) = if record_used { + self.hygienic_lexical_parent_with_compatibility_fallback(module, &mut ident.span) + } else { + (self.hygienic_lexical_parent(module, &mut ident.span), false) + }; + module = unwrap_or!(opt_module, break); let orig_current_module = self.current_module; self.current_module = module; // Lexical resolutions can never be a privacy error. let result = self.resolve_ident_in_module_unadjusted( @@ -1900,7 +1905,19 @@ impl<'a> Resolver<'a> { self.current_module = orig_current_module; match result { - Ok(binding) => return Some(LexicalScopeBinding::Item(binding)), + Ok(binding) => { + if poisoned { + self.session.buffer_lint_with_diagnostic( + lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + CRATE_NODE_ID, ident.span, + &format!("cannot find {} `{}` in this scope", ns.descr(), ident), + lint::builtin::BuiltinLintDiagnostics:: + ProcMacroDeriveResolutionFallback(ident.span), + ); + } + return Some(LexicalScopeBinding::Item(binding)) + } + _ if poisoned => break, Err(Undetermined) => return None, Err(Determined) => {} } @@ -1935,7 +1952,7 @@ impl<'a> Resolver<'a> { None } - fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span) + fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) -> Option> { if !module.expansion.is_descendant_of(span.ctxt().outer()) { return Some(self.macro_def_scope(span.remove_mark())); @@ -1945,22 +1962,41 @@ impl<'a> Resolver<'a> { return Some(module.parent.unwrap()); } - let mut module_expansion = module.expansion.modern(); // for backward compatibility - while let Some(parent) = module.parent { - let parent_expansion = parent.expansion.modern(); - if module_expansion.is_descendant_of(parent_expansion) && - parent_expansion != module_expansion { - return if parent_expansion.is_descendant_of(span.ctxt().outer()) { - Some(parent) - } else { - None - }; + None + } + + fn hygienic_lexical_parent_with_compatibility_fallback( + &mut self, module: Module<'a>, span: &mut Span) -> (Option>, /* poisoned */ bool + ) { + if let module @ Some(..) = self.hygienic_lexical_parent(module, span) { + return (module, false); + } + + // We need to support the next case under a deprecation warning + // ``` + // struct MyStruct; + // ---- begin: this comes from a proc macro derive + // mod implementation_details { + // // Note that `MyStruct` is not in scope here. + // impl SomeTrait for MyStruct { ... } + // } + // ---- end + // ``` + // So we have to fall back to the module's parent during lexical resolution in this case. + if let Some(parent) = module.parent { + // Inner module is inside the macro, parent module is outside of the macro. + if module.expansion != parent.expansion && + module.expansion.is_descendant_of(parent.expansion) { + // The macro is a proc macro derive + if module.expansion.looks_like_proc_macro_derive() { + if parent.expansion.is_descendant_of(span.ctxt().outer()) { + return (module.parent, true); + } + } } - module = parent; - module_expansion = parent_expansion; } - None + (None, false) } fn resolve_ident_in_module(&mut self, @@ -4037,8 +4073,9 @@ impl<'a> Resolver<'a> { let mut search_module = self.current_module; loop { self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); - search_module = - unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break); + search_module = unwrap_or!( + self.hygienic_lexical_parent(search_module, &mut ident.span), break + ); } if let Some(prelude) = self.prelude { @@ -4395,12 +4432,6 @@ impl<'a> Resolver<'a> { (TypeNS, _) => "type", }; - let namespace = match ns { - ValueNS => "value", - MacroNS => "macro", - TypeNS => "type", - }; - let msg = format!("the name `{}` is defined multiple times", name); let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { @@ -4418,7 +4449,7 @@ impl<'a> Resolver<'a> { err.note(&format!("`{}` must be defined only once in the {} namespace of this {}", name, - namespace, + ns.descr(), container)); err.span_label(span, format!("`{}` re{} here", name, new_participle)); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 385174ea7fea7..c7076478332f4 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -72,26 +72,16 @@ pub enum Transparency { } impl Mark { - fn fresh_with_data(mark_data: MarkData, data: &mut HygieneData) -> Self { - data.marks.push(mark_data); - Mark(data.marks.len() as u32 - 1) - } - pub fn fresh(parent: Mark) -> Self { HygieneData::with(|data| { - Mark::fresh_with_data(MarkData { + data.marks.push(MarkData { parent, // By default expansions behave like `macro_rules`. default_transparency: Transparency::SemiTransparent, is_builtin: false, expn_info: None, - }, data) - }) - } - - pub fn fresh_cloned(clone_from: Mark) -> Self { - HygieneData::with(|data| { - Mark::fresh_with_data(data.marks[clone_from.0 as usize].clone(), data) + }); + Mark(data.marks.len() as u32 - 1) }) } @@ -128,17 +118,6 @@ impl Mark { }) } - // FIXME: This operation doesn't really make sense when single macro expansion - // can produce tokens with different transparencies. Figure out how to avoid it. - pub fn modern(mut self) -> Mark { - HygieneData::with(|data| { - while data.marks[self.0 as usize].default_transparency != Transparency::Opaque { - self = data.marks[self.0 as usize].parent; - } - self - }) - } - #[inline] pub fn set_default_transparency(self, transparency: Transparency) { assert_ne!(self, Mark::root()); @@ -194,6 +173,24 @@ impl Mark { b }) } + + // Used for enabling some compatibility fallback in resolve. + #[inline] + pub fn looks_like_proc_macro_derive(self) -> bool { + HygieneData::with(|data| { + let mark_data = &data.marks[self.0 as usize]; + if mark_data.default_transparency == Transparency::Opaque { + if let Some(expn_info) = &mark_data.expn_info { + if let ExpnFormat::MacroAttribute(name) = expn_info.format { + if name.as_str().starts_with("derive(") { + return true; + } + } + } + } + false + }) + } } #[derive(Debug)] @@ -285,6 +282,7 @@ impl SyntaxContext { }) } + /// Extend a syntax context with a given mark and default transparency for that mark. pub fn apply_mark(self, mark: Mark) -> SyntaxContext { assert_ne!(mark, Mark::root()); self.apply_mark_with_transparency( diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs index 1741b0eed8927..6a8d545db49b9 100644 --- a/src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/generate-mod.rs @@ -20,9 +20,35 @@ use proc_macro::*; #[proc_macro] pub fn check(_: TokenStream) -> TokenStream { " + type Alias = FromOutside; // OK struct Outer; mod inner { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here type Inner = Outer; // `Outer` shouldn't be available from here } ".parse().unwrap() } + +#[proc_macro_attribute] +pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream { + " + type AliasAttr = FromOutside; // OK + struct OuterAttr; + mod inner_attr { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_derive(CheckDerive)] +pub fn check_derive(_: TokenStream) -> TokenStream { + " + type AliasDerive = FromOutside; // OK + struct OuterDerive; + mod inner_derive { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here + } + ".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/proc-macro/generate-mod.rs b/src/test/ui-fulldeps/proc-macro/generate-mod.rs index 509cd33d93d34..ff64421047fb8 100644 --- a/src/test/ui-fulldeps/proc-macro/generate-mod.rs +++ b/src/test/ui-fulldeps/proc-macro/generate-mod.rs @@ -12,10 +12,23 @@ // aux-build:generate-mod.rs -#![feature(proc_macro, proc_macro_gen)] +#![feature(proc_macro, proc_macro_gen, proc_macro_path_invoc)] extern crate generate_mod; -generate_mod::check!(); //~ ERROR cannot find type `Outer` in this scope +struct FromOutside; + +generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `Outer` in this scope + +#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterAttr` in this scope +struct S; + +#[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope + //~| WARN cannot find type `OuterDerive` in this scope + //~| WARN this was previously accepted + //~| WARN this was previously accepted +struct Z; fn main() {} diff --git a/src/test/ui-fulldeps/proc-macro/generate-mod.stderr b/src/test/ui-fulldeps/proc-macro/generate-mod.stderr index 80213b04dceb0..c024aeffbb086 100644 --- a/src/test/ui-fulldeps/proc-macro/generate-mod.stderr +++ b/src/test/ui-fulldeps/proc-macro/generate-mod.stderr @@ -1,9 +1,46 @@ +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:21:1 + | +LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + error[E0412]: cannot find type `Outer` in this scope - --> $DIR/generate-mod.rs:19:1 + --> $DIR/generate-mod.rs:21:1 | -LL | generate_mod::check!(); //~ ERROR cannot find type `Outer` in this scope +LL | generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:24:1 + | +LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `OuterAttr` in this scope + --> $DIR/generate-mod.rs:24:1 + | +LL | #[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:28:10 + | +LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: #[warn(proc_macro_derive_resolution_fallback)] 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 #50504 + +warning: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:28:10 + | +LL | #[derive(generate_mod::CheckDerive)] //~ WARN cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = 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 #50504 + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/run-pass/hygiene/arguments.rs b/src/test/ui/hygiene/arguments.rs similarity index 92% rename from src/test/run-pass/hygiene/arguments.rs rename to src/test/ui/hygiene/arguments.rs index 5d9e1863847da..958133e7ec589 100644 --- a/src/test/run-pass/hygiene/arguments.rs +++ b/src/test/ui/hygiene/arguments.rs @@ -23,5 +23,5 @@ macro m($t:ty, $e:expr) { fn main() { struct S; - m!(S, S); + m!(S, S); //~ ERROR cannot find type `S` in this scope } diff --git a/src/test/ui/hygiene/arguments.stderr b/src/test/ui/hygiene/arguments.stderr new file mode 100644 index 0000000000000..1b0c23eff297e --- /dev/null +++ b/src/test/ui/hygiene/arguments.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `S` in this scope + --> $DIR/arguments.rs:26:8 + | +LL | m!(S, S); //~ ERROR cannot find type `S` in this scope + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/hygiene/generate-mod.rs b/src/test/ui/hygiene/generate-mod.rs index 90409857deadc..2b2108558a0f3 100644 --- a/src/test/ui/hygiene/generate-mod.rs +++ b/src/test/ui/hygiene/generate-mod.rs @@ -12,13 +12,46 @@ #![feature(decl_macro, rustc_attrs)] +macro genmod($FromOutside: ident, $Outer: ident) { + type A = $FromOutside; + struct $Outer; + mod inner { + type A = $FromOutside; // `FromOutside` shouldn't be available from here + type Inner = $Outer; // `Outer` shouldn't be available from here + } +} + #[rustc_transparent_macro] -macro genmod() { - mod m { - type A = S; //~ ERROR cannot find type `S` in this scope +macro genmod_transparent() { + type A = FromOutside; + struct Outer; + mod inner { + type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope } } -struct S; +macro_rules! genmod_legacy { () => { + type A = FromOutside; + struct Outer; + mod inner { + type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope + } +}} -genmod!(); +fn check() { + struct FromOutside; + genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `Outer` in this scope +} + +fn check_transparent() { + struct FromOutside; + genmod_transparent!(); +} + +fn check_legacy() { + struct FromOutside; + genmod_legacy!(); +} diff --git a/src/test/ui/hygiene/generate-mod.stderr b/src/test/ui/hygiene/generate-mod.stderr index e79f8528c2cd7..0c5905c5acb4f 100644 --- a/src/test/ui/hygiene/generate-mod.stderr +++ b/src/test/ui/hygiene/generate-mod.stderr @@ -1,17 +1,56 @@ -error[E0412]: cannot find type `S` in this scope - --> $DIR/generate-mod.rs:18:18 +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:45:13 | -LL | type A = S; //~ ERROR cannot find type `S` in this scope - | ^ did you mean `A`? +LL | genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:45:26 + | +LL | genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^ not found in this scope + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:29:18 + | +LL | type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^ not found in this scope +... +LL | genmod_transparent!(); + | ---------------------- in this macro invocation + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:30:22 + | +LL | type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope + | ^^^^^ not found in this scope +... +LL | genmod_transparent!(); + | ---------------------- in this macro invocation + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:38:18 + | +LL | type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + | ^^^^^^^^^^^ not found in this scope +... +LL | genmod_legacy!(); + | ----------------- in this macro invocation + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:39:22 + | +LL | type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope + | ^^^^^ not found in this scope ... -LL | genmod!(); - | ---------- in this macro invocation +LL | genmod_legacy!(); + | ----------------- in this macro invocation error[E0601]: `main` function not found in crate `generate_mod` | = note: consider adding a `main` function to `$DIR/generate-mod.rs` -error: aborting due to 2 previous errors +error: aborting due to 7 previous errors Some errors occurred: E0412, E0601. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs index 7ba217061c66e..9785ce6c0048e 100644 --- a/src/test/ui/hygiene/globs.rs +++ b/src/test/ui/hygiene/globs.rs @@ -57,12 +57,26 @@ macro n($i:ident) { } } } + macro n_with_super($j:ident) { + mod test { + use super::*; + fn g() { + let _: u32 = $i(); + let _: () = f(); + super::$j(); + } + } + } - n!(f); + n!(f); //~ ERROR cannot find function `f` in this scope + n_with_super!(f); mod test2 { super::n! { f //~ ERROR cannot find function `f` in this scope } + super::n_with_super! { + f + } } } } diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index d77242e135dde..7df2e31f9a752 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -30,13 +30,23 @@ LL | use bar::g; | LL | use foo::test2::test::g; | -LL | use foo::test::g; +LL | use foo::test2::test::g; | LL | use foo::test::g; | +and 2 other candidates + +error[E0425]: cannot find function `f` in this scope + --> $DIR/globs.rs:71:12 + | +LL | n!(f); + | ------ in this macro invocation +... +LL | n!(f); //~ ERROR cannot find function `f` in this scope + | ^ not found in this scope error[E0425]: cannot find function `f` in this scope - --> $DIR/globs.rs:64:17 + --> $DIR/globs.rs:75:17 | LL | n!(f); | ------ in this macro invocation @@ -44,6 +54,6 @@ LL | n!(f); LL | f //~ ERROR cannot find function `f` in this scope | ^ not found in this scope -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0425`.