diff options
| author | bors <bors@rust-lang.org> | 2018-09-09 21:00:55 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-09-09 21:00:55 +0000 |
| commit | 2d4e34ca8bb1369f7e0eea4cb50e6faa0827a6e5 (patch) | |
| tree | 9e250b17aba2c7174bea5e7d7fb1a598da7e0ff2 /src | |
| parent | f50b7758f4dc85dc1c5e38258adaa94213ac6ed1 (diff) | |
| parent | 2dce3779bbc0353ff9fb544774417a851027fcab (diff) | |
| download | rust-2d4e34ca8bb1369f7e0eea4cb50e6faa0827a6e5.tar.gz rust-2d4e34ca8bb1369f7e0eea4cb50e6faa0827a6e5.zip | |
Auto merge of #53778 - petrochenkov:shadrelax2, r=nikomatsakis
resolve: Relax shadowing restrictions on macro-expanded macros Previously any macro-expanded macros weren't allowed to shadow macros from outer scopes. Now only "more macro-expanded" macros cannot shadow "less macro-expanded" macros. See comments to `fn may_appear_after` and added tests for more details and examples. The functional changes are a21f6f588fc28c97533130ae44a6957b579ab58c and 46dd365ce9ca0a6b8653849b80267763c542842a, other commits are refactorings.
Diffstat (limited to 'src')
27 files changed, 1230 insertions, 245 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 92a9057d96e..63f643d7a29 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -946,7 +946,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> { pub resolver: &'a mut Resolver<'b, 'c>, - pub legacy_scope: LegacyScope<'b>, + pub current_legacy_scope: LegacyScope<'b>, pub expansion: Mark, } @@ -956,7 +956,8 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> { self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); let invocation = self.resolver.invocations[&mark]; invocation.module.set(self.resolver.current_module); - invocation.legacy_scope.set(self.legacy_scope); + invocation.parent_legacy_scope.set(self.current_legacy_scope); + invocation.output_legacy_scope.set(self.current_legacy_scope); invocation } } @@ -982,29 +983,30 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { fn visit_item(&mut self, item: &'a Item) { let macro_use = match item.node { ItemKind::MacroDef(..) => { - self.resolver.define_macro(item, self.expansion, &mut self.legacy_scope); + self.resolver.define_macro(item, self.expansion, &mut self.current_legacy_scope); return } ItemKind::Mac(..) => { - self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); + self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(item.id)); return } ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), _ => false, }; - let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); + let orig_current_module = self.resolver.current_module; + let orig_current_legacy_scope = self.current_legacy_scope; self.resolver.build_reduced_graph_for_item(item, self.expansion); visit::walk_item(self, item); - self.resolver.current_module = parent; + self.resolver.current_module = orig_current_module; if !macro_use { - self.legacy_scope = legacy_scope; + self.current_legacy_scope = orig_current_legacy_scope; } } fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { if let ast::StmtKind::Mac(..) = stmt.node { - self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id)); + self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(stmt.id)); } else { visit::walk_stmt(self, stmt); } @@ -1021,11 +1023,12 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { } fn visit_block(&mut self, block: &'a Block) { - let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); + let orig_current_module = self.resolver.current_module; + let orig_current_legacy_scope = self.current_legacy_scope; self.resolver.build_reduced_graph_for_block(block, self.expansion); visit::walk_block(self, block); - self.resolver.current_module = parent; - self.legacy_scope = legacy_scope; + self.resolver.current_module = orig_current_module; + self.current_legacy_scope = orig_current_legacy_scope; } fn visit_trait_item(&mut self, item: &'a TraitItem) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 453e7421ff1..5cb615554ee 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1177,9 +1177,7 @@ struct UseError<'a> { } struct AmbiguityError<'a> { - span: Span, - name: Name, - lexical: bool, + ident: Ident, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>, } @@ -1283,6 +1281,26 @@ impl<'a> NameBinding<'a> { fn descr(&self) -> &'static str { if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() } } + + // Suppose that we resolved macro invocation with `invoc_id` to binding `binding` at some + // expansion round `max(invoc_id, binding)` when they both emerged from macros. + // Then this function returns `true` if `self` may emerge from a macro *after* that + // in some later round and screw up our previously found resolution. + // See more detailed explanation in + // https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 + fn may_appear_after(&self, invoc_id: Mark, binding: &NameBinding) -> bool { + // self > max(invoc_id, binding) => !(self <= invoc_id || self <= binding) + // Expansions are partially ordered, so "may appear after" is an inversion of + // "certainly appears before or simultaneously" and includes unordered cases. + let self_parent_expansion = self.expansion; + let other_parent_expansion = binding.expansion; + let invoc_parent_expansion = invoc_id.parent(); + let certainly_before_other_or_simultaneously = + other_parent_expansion.is_descendant_of(self_parent_expansion); + let certainly_before_invoc_or_simultaneously = + invoc_parent_expansion.is_descendant_of(self_parent_expansion); + !(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously) + } } /// Interns the names of the primitive types. @@ -1416,8 +1434,6 @@ pub struct Resolver<'a, 'b: 'a> { proc_mac_errors: Vec<macros::ProcMacError>, /// crate-local macro expanded `macro_export` referred to by a module-relative path macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, - /// macro-expanded `macro_rules` shadowing existing macros - disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, @@ -1729,7 +1745,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ambiguity_errors: Vec::new(), use_injections: Vec::new(), proc_mac_errors: Vec::new(), - disallowed_shadowing: Vec::new(), macro_expanded_macro_export_errors: BTreeSet::new(), arenas, @@ -1815,7 +1830,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.arenas.alloc_module(module) } - fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) + fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>) -> bool /* true if an error was reported */ { match binding.kind { NameBindingKind::Import { directive, binding, ref used } @@ -1824,13 +1839,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { directive.used.set(true); self.used_imports.insert((directive.id, ns)); self.add_to_glob_map(directive.id, ident); - self.record_use(ident, ns, binding, span) + self.record_use(ident, ns, binding) } NameBindingKind::Import { .. } => false, NameBindingKind::Ambiguity { b1, b2 } => { - self.ambiguity_errors.push(AmbiguityError { - span, name: ident.name, lexical: false, b1, b2, - }); + self.ambiguity_errors.push(AmbiguityError { ident, b1, b2 }); true } _ => false @@ -2850,7 +2863,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { Def::Const(..) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant // or constant pattern. - self.record_use(ident, ValueNS, binding.unwrap(), ident.span); + self.record_use(ident, ValueNS, binding.unwrap()); Some(PathResolution::new(def)) } Def::StructCtor(..) | Def::VariantCtor(..) | @@ -3484,6 +3497,20 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { path_span: Span, crate_lint: CrateLint, ) -> PathResult<'a> { + self.resolve_path_with_invoc_id(base_module, path, opt_ns, Mark::root(), + record_used, path_span, crate_lint) + } + + fn resolve_path_with_invoc_id( + &mut self, + base_module: Option<ModuleOrUniformRoot<'a>>, + path: &[Ident], + opt_ns: Option<Namespace>, // `None` indicates a module path + invoc_id: Mark, + record_used: bool, + path_span: Span, + crate_lint: CrateLint, + ) -> PathResult<'a> { let mut module = base_module; let mut allow_super = true; let mut second_binding = None; @@ -3572,8 +3599,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.resolve_ident_in_module(module, ident, ns, record_used, path_span) } else if opt_ns == Some(MacroNS) { assert!(ns == TypeNS); - self.resolve_lexical_macro_path_segment(ident, ns, record_used, record_used, - false, path_span).map(|(b, _)| b) + self.resolve_lexical_macro_path_segment(ident, ns, invoc_id, record_used, + record_used, false, path_span) + .map(|(binding, _)| binding) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; @@ -4514,35 +4542,33 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { vis.is_accessible_from(module.normal_ancestor_id, self) } - fn report_ambiguity_error( - &self, name: Name, span: Span, _lexical: bool, - def1: Def, is_import1: bool, is_glob1: bool, from_expansion1: bool, span1: Span, - def2: Def, is_import2: bool, _is_glob2: bool, _from_expansion2: bool, span2: Span, - ) { + fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBinding) { let participle = |is_import: bool| if is_import { "imported" } else { "defined" }; - let msg1 = format!("`{}` could refer to the name {} here", name, participle(is_import1)); + let msg1 = + format!("`{}` could refer to the name {} here", ident, participle(b1.is_import())); let msg2 = - format!("`{}` could also refer to the name {} here", name, participle(is_import2)); - let note = if from_expansion1 { - Some(if let Def::Macro(..) = def1 { + format!("`{}` could also refer to the name {} here", ident, participle(b2.is_import())); + let note = if b1.expansion != Mark::root() { + Some(if let Def::Macro(..) = b1.def() { format!("macro-expanded {} do not shadow", - if is_import1 { "macro imports" } else { "macros" }) + if b1.is_import() { "macro imports" } else { "macros" }) } else { format!("macro-expanded {} do not shadow when used in a macro invocation path", - if is_import1 { "imports" } else { "items" }) + if b1.is_import() { "imports" } else { "items" }) }) - } else if is_glob1 { - Some(format!("consider adding an explicit import of `{}` to disambiguate", name)) + } else if b1.is_glob_import() { + Some(format!("consider adding an explicit import of `{}` to disambiguate", ident)) } else { None }; - let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name); - err.span_note(span1, &msg1); - match def2 { - Def::Macro(..) if span2.is_dummy() => - err.note(&format!("`{}` is also a builtin macro", name)), - _ => err.span_note(span2, &msg2), + let mut err = struct_span_err!(self.session, ident.span, E0659, "`{}` is ambiguous", ident); + err.span_label(ident.span, "ambiguous name"); + err.span_note(b1.span, &msg1); + match b2.def() { + Def::Macro(..) if b2.span.is_dummy() => + err.note(&format!("`{}` is also a builtin macro", ident)), + _ => err.span_note(b2.span, &msg2), }; if let Some(note) = note { err.note(¬e); @@ -4551,7 +4577,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn report_errors(&mut self, krate: &Crate) { - self.report_shadowing_errors(); self.report_with_use_injections(krate); self.report_proc_macro_import(krate); let mut reported_spans = FxHashSet(); @@ -4567,15 +4592,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ); } - for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { - if reported_spans.insert(span) { - self.report_ambiguity_error( - name, span, lexical, - b1.def(), b1.is_import(), b1.is_glob_import(), - b1.expansion != Mark::root(), b1.span, - b2.def(), b2.is_import(), b2.is_glob_import(), - b2.expansion != Mark::root(), b2.span, - ); + for &AmbiguityError { ident, b1, b2 } in &self.ambiguity_errors { + if reported_spans.insert(ident.span) { + self.report_ambiguity_error(ident, b1, b2); } } @@ -4595,20 +4614,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } - fn report_shadowing_errors(&mut self) { - let mut reported_errors = FxHashSet(); - for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { - if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() && - reported_errors.insert((binding.ident, binding.span)) { - let msg = format!("`{}` is already in scope", binding.ident); - self.session.struct_span_err(binding.span, &msg) - .note("macro-expanded `macro_rules!`s may not shadow \ - existing macros (see RFC 1560)") - .emit(); - } - } - } - fn report_conflict<'b>(&mut self, parent: Module, ident: Ident, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fc6e0eb3b7f..93874ee0e85 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -45,18 +45,21 @@ use std::mem; use rustc_data_structures::sync::Lrc; use rustc_data_structures::small_vec::ExpectOne; +#[derive(Clone, Copy)] crate struct FromPrelude(bool); -crate struct FromExpansion(bool); #[derive(Clone)] pub struct InvocationData<'a> { - pub module: Cell<Module<'a>>, - pub def_index: DefIndex, - // The scope in which the invocation path is resolved. - pub legacy_scope: Cell<LegacyScope<'a>>, - // The smallest scope that includes this invocation's expansion, - // or `Empty` if this invocation has not been expanded yet. - pub expansion: Cell<LegacyScope<'a>>, + def_index: DefIndex, + /// Module in which the macro was invoked. + crate module: Cell<Module<'a>>, + /// Legacy scope in which the macro was invoked. + /// The invocation path is resolved in this scope. + crate parent_legacy_scope: Cell<LegacyScope<'a>>, + /// Legacy scope *produced* by expanding this macro invocation, + /// includes all the macro_rules items, other invocations, etc generated by it. + /// Set to the parent scope if the macro is not expanded yet (as if the macro produced nothing). + crate output_legacy_scope: Cell<LegacyScope<'a>>, } impl<'a> InvocationData<'a> { @@ -64,31 +67,38 @@ impl<'a> InvocationData<'a> { InvocationData { module: Cell::new(graph_root), def_index: CRATE_DEF_INDEX, - legacy_scope: Cell::new(LegacyScope::Empty), - expansion: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Empty), + output_legacy_scope: Cell::new(LegacyScope::Empty), } } } +/// Binding produced by a `macro_rules` item. +/// Not modularized, can shadow previous legacy bindings, etc. +pub struct LegacyBinding<'a> { + binding: &'a NameBinding<'a>, + /// Legacy scope into which the `macro_rules` item was planted. + parent_legacy_scope: LegacyScope<'a>, + ident: Ident, +} + +/// Scope introduced by a `macro_rules!` macro. +/// Starts at the macro's definition and ends at the end of the macro's parent module +/// (named or unnamed), or even further if it escapes with `#[macro_use]`. +/// Some macro invocations need to introduce legacy scopes too because they +/// potentially can expand into macro definitions. #[derive(Copy, Clone)] pub enum LegacyScope<'a> { + /// Created when invocation data is allocated in the arena, + /// must be replaced with a proper scope later. + Uninitialized, + /// Empty "root" scope at the crate start containing no names. Empty, - Invocation(&'a InvocationData<'a>), // The scope of the invocation, not including its expansion - Expansion(&'a InvocationData<'a>), // The scope of the invocation, including its expansion + /// Scope introduced by a `macro_rules!` macro definition. Binding(&'a LegacyBinding<'a>), -} - -pub struct LegacyBinding<'a> { - pub parent: Cell<LegacyScope<'a>>, - pub ident: Ident, - def_id: DefId, - pub span: Span, -} - -impl<'a> LegacyBinding<'a> { - fn def(&self) -> Def { - Def::Macro(self.def_id, MacroKind::Bang) - } + /// Scope introduced by a macro invocation that can potentially + /// create a `macro_rules!` macro definition. + Invocation(&'a InvocationData<'a>), } pub struct ProcMacError { @@ -110,8 +120,8 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData { module: Cell::new(module), def_index: module.def_id().unwrap().index, - legacy_scope: Cell::new(LegacyScope::Empty), - expansion: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Empty), + output_legacy_scope: Cell::new(LegacyScope::Empty), })); mark } @@ -183,11 +193,11 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { } let mut visitor = BuildReducedGraphVisitor { resolver: self, - legacy_scope: LegacyScope::Invocation(invocation), + current_legacy_scope: invocation.parent_legacy_scope.get(), expansion: mark, }; fragment.visit_with(&mut visitor); - invocation.expansion.set(visitor.legacy_scope); + invocation.output_legacy_scope.set(visitor.current_legacy_scope); } fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) { @@ -437,12 +447,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { Ok((def, self.get_macro(def))) } - pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark, + pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark, derives_in_scope: &[ast::Path], force: bool) -> Result<Def, Determinacy> { let ast::Path { ref segments, span } = *path; let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); - let invocation = self.invocations[&scope]; + let invocation = self.invocations[&invoc_id]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; @@ -454,8 +464,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } if path.len() > 1 { - let res = self.resolve_path(None, &path, Some(MacroNS), false, span, CrateLint::No); - let def = match res { + let def = match self.resolve_path_with_invoc_id(None, &path, Some(MacroNS), invoc_id, + false, span, CrateLint::No) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => { @@ -486,11 +496,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); - let result = if let Some((legacy_binding, _)) = legacy_resolution { + let legacy_resolution = self.resolve_legacy_scope( + path[0], invoc_id, invocation.parent_legacy_scope.get(), false + ); + let result = if let Some(legacy_binding) = legacy_resolution { Ok(legacy_binding.def()) } else { - match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, force, + match self.resolve_lexical_macro_path_segment(path[0], MacroNS, invoc_id, false, force, kind == MacroKind::Attr, span) { Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()), Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), @@ -502,7 +514,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }; self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path[0], kind, result.ok())); + .push((invoc_id, path[0], kind, result.ok())); if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else { return result; @@ -521,7 +533,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { enum ConvertToDeriveHelper { Yes, No, DontKnow } let mut convert_to_derive_helper = ConvertToDeriveHelper::No; for derive in derives_in_scope { - match self.resolve_macro_path(derive, MacroKind::Derive, scope, &[], force) { + match self.resolve_macro_path(derive, MacroKind::Derive, invoc_id, &[], force) { Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext { if inert_attrs.contains(&path[0].name) { convert_to_derive_helper = ConvertToDeriveHelper::Yes; @@ -549,10 +561,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { &mut self, mut ident: Ident, ns: Namespace, + invoc_id: Mark, record_used: bool, force: bool, is_attr: bool, - path_span: Span + path_span: Span, ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names @@ -585,15 +598,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { assert!(force || !record_used); // `record_used` implies `force` ident = ident.modern(); - // Names from inner scope that can't shadow names from outer scopes, e.g. - // mod m { ... } + // This is *the* result, resolution from the scope closest to the resolved identifier. + // However, sometimes this result is "weak" because it comes from a glob import or + // a macro expansion, and in this case it cannot shadow names from outer scopes, e.g. + // mod m { ... } // solution in outer scope // { - // use prefix::*; // if this imports another `m`, then it can't shadow the outer `m` - // // and we have and ambiguity error + // use prefix::*; // imports another `m` - innermost solution + // // weak, cannot shadow the outer `m`, need to report ambiguity error // m::mac!(); // } - // This includes names from globs and from macro expansions. - let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None; + // So we have to save the innermost solution and continue searching in outer scopes + // to detect potential ambiguities. + let mut innermost_result: Option<(&NameBinding, FromPrelude)> = None; enum WhereToResolve<'a> { Module(Module<'a>), @@ -736,33 +752,24 @@ impl<'a, 'cl> Resolver<'a, 'cl> { return Ok(result); } - // Found a solution that is ambiguous with a previously found solution. - // Push an ambiguity error for later reporting and - // return something for better recovery. - if let Some(previous_result) = potentially_ambiguous_result { - if result.0.def() != previous_result.0.def() { + if let Some(innermost_result) = innermost_result { + // Found another solution, if the first one was "weak", report an error. + if result.0.def() != innermost_result.0.def() && + (innermost_result.0.is_glob_import() || + innermost_result.0.may_appear_after(invoc_id, result.0)) { self.ambiguity_errors.push(AmbiguityError { - span: path_span, - name: ident.name, - b1: previous_result.0, + ident, + b1: innermost_result.0, b2: result.0, - lexical: true, }); - return Ok(previous_result); + return Ok(innermost_result); } + } else { + // Found the first solution. + innermost_result = Some(result); } - // Found a solution that's not an ambiguity yet, but is "suspicious" and - // can participate in ambiguities later on. - // Remember it and go search for other solutions in outer scopes. - if result.0.is_glob_import() || result.0.expansion != Mark::root() { - potentially_ambiguous_result = Some(result); - - continue_search!(); - } - - // Found a solution that can't be ambiguous, great success. - return Ok(result); + continue_search!(); }, Err(Determinacy::Determined) => { continue_search!(); @@ -771,9 +778,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } - // Previously found potentially ambiguous result turned out to not be ambiguous after all. - if let Some(previous_result) = potentially_ambiguous_result { - return Ok(previous_result); + // The first found solution was the only one, return it. + if let Some(innermost_result) = innermost_result { + return Ok(innermost_result); } let determinacy = Determinacy::determined(force); @@ -791,45 +798,79 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } - crate fn resolve_legacy_scope(&mut self, - mut scope: &'a Cell<LegacyScope<'a>>, - ident: Ident, - record_used: bool) - -> Option<(&'a LegacyBinding<'a>, FromExpansion)> { + fn resolve_legacy_scope(&mut self, + ident: Ident, + invoc_id: Mark, + invoc_parent_legacy_scope: LegacyScope<'a>, + record_used: bool) + -> Option<&'a NameBinding<'a>> { let ident = ident.modern(); - let mut relative_depth: u32 = 0; + + // This is *the* result, resolution from the scope closest to the resolved identifier. + // However, sometimes this result is "weak" because it comes from a macro expansion, + // and in this case it cannot shadow names from outer scopes, e.g. + // macro_rules! m { ... } // solution in outer scope + // { + // define_m!(); // generates another `macro_rules! m` - innermost solution + // // weak, cannot shadow the outer `m`, need to report ambiguity error + // m!(); + // } + // So we have to save the innermost solution and continue searching in outer scopes + // to detect potential ambiguities. + let mut innermost_result: Option<&NameBinding> = None; + + // Go through all the scopes and try to resolve the name. + let mut where_to_resolve = invoc_parent_legacy_scope; loop { - match scope.get() { - LegacyScope::Empty => break, - LegacyScope::Expansion(invocation) => { - match invocation.expansion.get() { - LegacyScope::Invocation(_) => scope.set(invocation.legacy_scope.get()), - LegacyScope::Empty => { - scope = &invocation.legacy_scope; - } - _ => { - relative_depth += 1; - scope = &invocation.expansion; - } + let result = match where_to_resolve { + LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => + Some(legacy_binding.binding), + _ => None, + }; + + macro_rules! continue_search { () => { + where_to_resolve = match where_to_resolve { + LegacyScope::Empty => break, // nowhere else to search + LegacyScope::Binding(binding) => binding.parent_legacy_scope, + LegacyScope::Invocation(invocation) => invocation.output_legacy_scope.get(), + LegacyScope::Uninitialized => unreachable!(), + }; + + continue; + }} + + match result { + Some(result) => { + if !record_used { + return Some(result); } - } - LegacyScope::Invocation(invocation) => { - relative_depth = relative_depth.saturating_sub(1); - scope = &invocation.legacy_scope; - } - LegacyScope::Binding(potential_binding) => { - if potential_binding.ident == ident { - if record_used && relative_depth > 0 { - self.disallowed_shadowing.push(potential_binding); + + if let Some(innermost_result) = innermost_result { + // Found another solution, if the first one was "weak", report an error. + if result.def() != innermost_result.def() && + innermost_result.may_appear_after(invoc_id, result) { + self.ambiguity_errors.push(AmbiguityError { + ident, + b1: innermost_result, + b2: result, + }); + return Some(innermost_result); } - return Some((potential_binding, FromExpansion(relative_depth > 0))); + } else { + // Found the first solution. + innermost_result = Some(result); } - scope = &potential_binding.parent; + + continue_search!(); } - }; + None => { + continue_search!(); + } + } } - None + // The first found solution was the only one (or there was no solution at all), return it. + innermost_result } pub fn finalize_current_module_macro_resolutions(&mut self) { @@ -844,17 +885,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } - for &(mark, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() { + for &(invoc_id, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() { let span = ident.span; - let legacy_scope = &self.invocations[&mark].legacy_scope; - let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true); - let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, true, - kind == MacroKind::Attr, span); + let invocation = self.invocations[&invoc_id]; + let legacy_resolution = self.resolve_legacy_scope( + ident, invoc_id, invocation.parent_legacy_scope.get(), true + ); + let resolution = self.resolve_lexical_macro_path_segment( + ident, MacroNS, invoc_id, true, true, kind == MacroKind::Attr, span + ); let check_consistency = |this: &Self, new_def: Def| { if let Some(def) = def { - if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() && - new_def != def && new_def != Def::Err { + if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err { // Make sure compilation does not succeed if preferred macro resolution // has changed after the macro had been expanded. In theory all such // situations should be reported as ambiguity errors, so this is span-bug. @@ -882,31 +925,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.suggest_macro_name(&ident.as_str(), kind, &mut err, span); err.emit(); }, - (Some((legacy_binding, FromExpansion(from_expansion))), - Ok((binding, FromPrelude(false)))) | - (Some((legacy_binding, FromExpansion(from_expansion @ true))), - Ok((binding, FromPrelude(true)))) => { - if legacy_binding.def() != binding.def_ignoring_ambiguity() { - self.report_ambiguity_error( - ident.name, span, true, - legacy_binding.def(), false, false, - from_expansion, legacy_binding.span, - binding.def(), binding.is_import(), binding.is_glob_import(), - binding.expansion != Mark::root(), binding.span, - ); + (Some(legacy_binding), Ok((binding, FromPrelude(from_prelude)))) + if !from_prelude || legacy_binding.may_appear_after(invoc_id, binding) => { + if legacy_binding.def_ignoring_ambiguity() != binding.def_ignoring_ambiguity() { + self.report_ambiguity_error(ident, legacy_binding, binding); } }, - // OK, non-macro-expanded legacy wins over macro prelude even if defs are different - (Some((legacy_binding, FromExpansion(false))), Ok((_, FromPrelude(true)))) | + // OK, non-macro-expanded legacy wins over prelude even if defs are different + (Some(legacy_binding), Ok(_)) | // OK, unambiguous resolution - (Some((legacy_binding, _)), Err(_)) => { + (Some(legacy_binding), Err(_)) => { check_consistency(self, legacy_binding.def()); } // OK, unambiguous resolution (None, Ok((binding, FromPrelude(from_prelude)))) => { check_consistency(self, binding.def_ignoring_ambiguity()); if from_prelude { - self.record_use(ident, MacroNS, binding, span); + self.record_use(ident, MacroNS, binding); self.err_if_macro_use_proc_macro(ident.name, span, binding); } } @@ -981,8 +1016,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { arenas.alloc_invocation_data(InvocationData { def_index: invoc.def_index, module: Cell::new(graph_root), - expansion: Cell::new(LegacyScope::Empty), - legacy_scope: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Uninitialized), + output_legacy_scope: Cell::new(LegacyScope::Uninitialized), }) }); }; @@ -997,7 +1032,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { pub fn define_macro(&mut self, item: &ast::Item, expansion: Mark, - legacy_scope: &mut LegacyScope<'a>) { + current_legacy_scope: &mut LegacyScope<'a>) { self.local_macro_def_scopes.insert(item.id, self.current_module); let ident = item.ident; if ident.name == "macro_rules" { @@ -1014,10 +1049,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if def.legacy { let ident = ident.modern(); self.macro_names.insert(ident); - *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding { - parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span, - })); let def = Def::Macro(def_id, MacroKind::Bang); + let vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings + let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas); + let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding { + parent_legacy_scope: *current_legacy_scope, binding, ident + }); + *current_legacy_scope = LegacyScope::Binding(legacy_binding); self.all_macros.insert(ident.name, def); if attr::contains_name(&item.attrs, "macro_export") { let module = self.graph_root; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index a72ee7ae379..f8767fa553f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -242,22 +242,19 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { if record_used { if let Some(binding) = resolution.binding { if let Some(shadowed_glob) = resolution.shadowed_glob { - let name = ident.name; // Forbid expanded shadowing to avoid time travel. if restricted_shadowing && binding.expansion != Mark::root() && ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing binding.def() != shadowed_glob.def() { self.ambiguity_errors.push(AmbiguityError { - span: path_span, - name, - lexical: false, + ident, b1: binding, b2: shadowed_glob, }); } } - if self.record_use(ident, ns, binding, path_span) { + if self.record_use(ident, ns, binding) { return Ok(self.dummy_binding); } if !self.is_accessible(binding.vis) { @@ -937,7 +934,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { if let Ok(binding) = result[ns].get() { all_ns_err = false; - if this.record_use(ident, ns, binding, directive.span) { + if this.record_use(ident, ns, binding) { if let ModuleOrUniformRoot::Module(module) = module { this.resolution(module, ident, ns).borrow_mut().binding = Some(this.dummy_binding); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9a9fb055292..e912482cf58 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -966,6 +966,10 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "the `#[rustc_test_marker]` attribute \ is used internally to track tests", cfg_fn!(rustc_attrs))), + ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "used internally for testing macro hygiene", + cfg_fn!(rustc_attrs))), // RFC #2094 ("nll", Whitelisted, Gated(Stability::Unstable, diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 7e985cf52f5..f053cb10d06 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -101,6 +101,11 @@ impl Mark { } #[inline] + pub fn parent(self) -> Mark { + HygieneData::with(|data| data.marks[self.0 as usize].parent) + } + + #[inline] pub fn expn_info(self) -> Option<ExpnInfo> { HygieneData::with(|data| data.marks[self.0 as usize].expn_info.clone()) } diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr index 06176085b38..f168b7797ca 100644 --- a/src/test/ui/error-codes/E0659.stderr +++ b/src/test/ui/error-codes/E0659.stderr @@ -1,8 +1,8 @@ error[E0659]: `foo` is ambiguous - --> $DIR/E0659.rs:25:5 + --> $DIR/E0659.rs:25:15 | LL | collider::foo(); //~ ERROR E0659 - | ^^^^^^^^^^^^^ + | ^^^ ambiguous name | note: `foo` could refer to the name imported here --> $DIR/E0659.rs:20:13 diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 452e3e1e200..9cdd7aa88f1 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -13,10 +13,10 @@ LL | use a::foo as other_foo; //~ ERROR the name `foo` is defined multiple t | ^^^^^^^^^^^^^^^^^^^ error[E0659]: `foo` is ambiguous - --> $DIR/duplicate.rs:56:9 + --> $DIR/duplicate.rs:56:15 | LL | use self::foo::bar; //~ ERROR `foo` is ambiguous - | ^^^^^^^^^^^^^^ + | ^^^ ambiguous name | note: `foo` could refer to the name imported here --> $DIR/duplicate.rs:53:9 @@ -31,10 +31,10 @@ LL | use self::m2::*; = note: consider adding an explicit import of `foo` to disambiguate error[E0659]: `foo` is ambiguous - --> $DIR/duplicate.rs:45:5 + --> $DIR/duplicate.rs:45:8 | LL | f::foo(); //~ ERROR `foo` is ambiguous - | ^^^^^^ + | ^^^ ambiguous name | note: `foo` could refer to the name imported here --> $DIR/duplicate.rs:34:13 @@ -49,10 +49,10 @@ LL | pub use b::*; = note: consider adding an explicit import of `foo` to disambiguate error[E0659]: `foo` is ambiguous - --> $DIR/duplicate.rs:46:5 + --> $DIR/duplicate.rs:46:8 | LL | g::foo(); //~ ERROR `foo` is ambiguous - | ^^^^^^ + | ^^^ ambiguous name | note: `foo` could refer to the name imported here --> $DIR/duplicate.rs:39:13 @@ -70,7 +70,7 @@ error[E0659]: `foo` is ambiguous --> $DIR/duplicate.rs:59:9 | LL | foo::bar(); //~ ERROR `foo` is ambiguous - | ^^^^^^^^ + | ^^^ ambiguous name | note: `foo` could refer to the name imported here --> $DIR/duplicate.rs:53:9 diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr index 7f61cd6c76d..33a2963fa29 100644 --- a/src/test/ui/imports/glob-shadowing.stderr +++ b/src/test/ui/imports/glob-shadowing.stderr @@ -2,7 +2,7 @@ error[E0659]: `env` is ambiguous --> $DIR/glob-shadowing.rs:21:17 | LL | let x = env!("PATH"); //~ ERROR `env` is ambiguous - | ^^^ + | ^^^ ambiguous name | note: `env` could refer to the name imported here --> $DIR/glob-shadowing.rs:19:9 @@ -16,7 +16,7 @@ error[E0659]: `env` is ambiguous --> $DIR/glob-shadowing.rs:29:21 | LL | let x = env!("PATH"); //~ ERROR `env` is ambiguous - | ^^^ + | ^^^ ambiguous name | note: `env` could refer to the name imported here --> $DIR/glob-shadowing.rs:27:13 @@ -30,7 +30,7 @@ error[E0659]: `fenv` is ambiguous --> $DIR/glob-shadowing.rs:39:21 | LL | let x = fenv!(); //~ ERROR `fenv` is ambiguous - | ^^^^ + | ^^^^ ambiguous name | note: `fenv` could refer to the name imported here --> $DIR/glob-shadowing.rs:37:13 diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr index 0036d71107a..e125983151d 100644 --- a/src/test/ui/imports/issue-53269.stderr +++ b/src/test/ui/imports/issue-53269.stderr @@ -8,7 +8,7 @@ error[E0659]: `mac` is ambiguous --> $DIR/issue-53269.rs:18:5 | LL | mac!(); //~ ERROR `mac` is ambiguous - | ^^^ + | ^^^ ambiguous name | note: `mac` could refer to the name defined here --> $DIR/issue-53269.rs:13:1 diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs index 445344732f7..fb05b95a96d 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs @@ -43,7 +43,6 @@ mod inner2 { fn main() { panic!(); //~ ERROR `panic` is ambiguous - //~^ ERROR `panic` is ambiguous } mod inner3 { diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index e9a81e7ae4c..cce1fd30f1d 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -2,7 +2,7 @@ error[E0659]: `exported` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:38:1 | LL | exported!(); //~ ERROR `exported` is ambiguous - | ^^^^^^^^ + | ^^^^^^^^ ambiguous name | note: `exported` could refer to the name defined here --> $DIR/local-modularized-tricky-fail-1.rs:15:5 @@ -22,10 +22,10 @@ LL | use inner1::*; = note: macro-expanded macros do not shadow error[E0659]: `include` is ambiguous - --> $DIR/local-modularized-tricky-fail-1.rs:57:1 + --> $DIR/local-modularized-tricky-fail-1.rs:56:1 | LL | include!(); //~ ERROR `include` is ambiguous - | ^^^^^^^ + | ^^^^^^^ ambiguous name | note: `include` could refer to the name defined here --> $DIR/local-modularized-tricky-fail-1.rs:27:5 @@ -44,7 +44,7 @@ error[E0659]: `panic` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:45:5 | LL | panic!(); //~ ERROR `panic` is ambiguous - | ^^^^^ + | ^^^^^ ambiguous name | note: `panic` could refer to the name defined here --> $DIR/local-modularized-tricky-fail-1.rs:21:5 @@ -60,10 +60,10 @@ LL | define_panic!(); = note: macro-expanded macros do not shadow error[E0659]: `panic` is ambiguous - --> $DIR/local-modularized-tricky-fail-1.rs:45:5 + --> <panic macros>:1:13 | -LL | panic!(); //~ ERROR `panic` is ambiguous - | ^^^^^^^^^ +LL | ( ) => ( { panic ! ( "explicit panic" ) } ) ; ( $ msg : expr ) => ( + | ^^^^^ ambiguous name | note: `panic` could refer to the name defined here --> $DIR/local-modularized-tricky-fail-1.rs:21:5 @@ -77,7 +77,6 @@ LL | define_panic!(); | ---------------- in this macro invocation = note: `panic` is also a builtin macro = note: macro-expanded macros do not shadow - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index 08f45e1a575..a612c64c2f4 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -2,7 +2,7 @@ error[E0659]: `bar` is ambiguous --> $DIR/macro-paths.rs:23:5 | LL | bar::m! { //~ ERROR ambiguous - | ^^^^^^ + | ^^^ ambiguous name | note: `bar` could refer to the name defined here --> $DIR/macro-paths.rs:24:9 @@ -20,7 +20,7 @@ error[E0659]: `baz` is ambiguous --> $DIR/macro-paths.rs:33:5 | LL | baz::m! { //~ ERROR ambiguous - | ^^^^^^ + | ^^^ ambiguous name | note: `baz` could refer to the name defined here --> $DIR/macro-paths.rs:34:9 diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index 2c0c4642067..c54101fc6e6 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -2,7 +2,7 @@ error[E0659]: `m` is ambiguous --> $DIR/macros.rs:48:5 | LL | m!(); //~ ERROR ambiguous - | ^ + | ^ ambiguous name | note: `m` could refer to the name defined here --> $DIR/macros.rs:46:5 @@ -19,7 +19,7 @@ error[E0659]: `m` is ambiguous --> $DIR/macros.rs:26:5 | LL | m! { //~ ERROR ambiguous - | ^ + | ^ ambiguous name | note: `m` could refer to the name imported here --> $DIR/macros.rs:27:13 @@ -37,7 +37,7 @@ error[E0659]: `m` is ambiguous --> $DIR/macros.rs:39:9 | LL | m! { //~ ERROR ambiguous - | ^ + | ^ ambiguous name | note: `m` could refer to the name imported here --> $DIR/macros.rs:40:17 diff --git a/src/test/ui/imports/rfc-1560-warning-cycle.stderr b/src/test/ui/imports/rfc-1560-warning-cycle.stderr index 5a01680fc19..91af3a4b6ac 100644 --- a/src/test/ui/imports/rfc-1560-warning-cycle.stderr +++ b/src/test/ui/imports/rfc-1560-warning-cycle.stderr @@ -2,7 +2,7 @@ error[E0659]: `Foo` is ambiguous --> $DIR/rfc-1560-warning-cycle.rs:19:17 | LL | fn f(_: Foo) {} //~ ERROR `Foo` is ambiguous - | ^^^ + | ^^^ ambiguous name | note: `Foo` could refer to the name imported here --> $DIR/rfc-1560-warning-cycle.rs:17:13 diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 5c7f15b6fe2..e554bbb4f31 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -2,7 +2,7 @@ error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:43:5 | LL | panic!(); //~ ERROR `panic` is ambiguous - | ^^^^^ + | ^^^^^ ambiguous name | note: `panic` could refer to the name defined here --> $DIR/shadow_builtin_macros.rs:40:9 @@ -19,7 +19,7 @@ error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:25:14 | LL | fn f() { panic!(); } //~ ERROR ambiguous - | ^^^^^ + | ^^^^^ ambiguous name | note: `panic` could refer to the name imported here --> $DIR/shadow_builtin_macros.rs:24:9 @@ -33,7 +33,7 @@ error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:30:14 | LL | fn f() { panic!(); } //~ ERROR ambiguous - | ^^^^^ + | ^^^^^ ambiguous name | note: `panic` could refer to the name imported here --> $DIR/shadow_builtin_macros.rs:29:26 @@ -47,7 +47,7 @@ error[E0659]: `n` is ambiguous --> $DIR/shadow_builtin_macros.rs:59:5 | LL | n!(); //~ ERROR ambiguous - | ^ + | ^ ambiguous name | note: `n` could refer to the name imported here --> $DIR/shadow_builtin_macros.rs:58:9 diff --git a/src/test/ui/macros/auxiliary/macro-in-other-crate.rs b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs index c787cedc2d0..7f716c5012e 100644 --- a/src/test/ui/macros/auxiliary/macro-in-other-crate.rs +++ b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs @@ -17,3 +17,8 @@ macro_rules! mac { macro_rules! inline { () => () } + +#[macro_export] +macro_rules! from_prelude { + () => () +} diff --git a/src/test/ui/macros/macro-path-prelude-shadowing.stderr b/src/test/ui/macros/macro-path-prelude-shadowing.stderr index c0892f97376..607d3e100aa 100644 --- a/src/test/ui/macros/macro-path-prelude-shadowing.stderr +++ b/src/test/ui/macros/macro-path-prelude-shadowing.stderr @@ -2,7 +2,7 @@ error[E0659]: `std` is ambiguous --> $DIR/macro-path-prelude-shadowing.rs:39:9 | LL | std::panic!(); //~ ERROR `std` is ambiguous - | ^^^^^^^^^^ + | ^^^ ambiguous name | note: `std` could refer to the name imported here --> $DIR/macro-path-prelude-shadowing.rs:37:9 diff --git a/src/test/ui/macros/macro-shadowing-relaxed.rs b/src/test/ui/macros/macro-shadowing-relaxed.rs new file mode 100644 index 00000000000..8d5b03b098f --- /dev/null +++ b/src/test/ui/macros/macro-shadowing-relaxed.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// aux-build:macro-in-other-crate.rs + +#![feature(decl_macro)] + +macro_rules! my_include {() => { + // Outer + macro m() {} + #[macro_use(from_prelude)] extern crate macro_in_other_crate; + + fn inner() { + // Inner + macro m() {} + macro_rules! from_prelude { () => {} } + + // OK, both `m` and `from_prelude` are macro-expanded, + // but no more macro-expanded than their counterpart from outer scope. + m!(); + from_prelude!(); + } +}} + +my_include!(); + +fn main() {} diff --git a/src/test/ui/macros/macro-shadowing.rs b/src/test/ui/macros/macro-shadowing.rs index 61abaf8a2dd..bf0a7fa21d3 100644 --- a/src/test/ui/macros/macro-shadowing.rs +++ b/src/test/ui/macros/macro-shadowing.rs @@ -17,14 +17,14 @@ macro_rules! macro_one { () => {} } #[macro_use(macro_two)] extern crate two_macros; macro_rules! m1 { () => { - macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope + macro_rules! foo { () => {} } #[macro_use] //~ ERROR `macro_two` is already in scope extern crate two_macros as __; }} m1!(); -foo!(); +foo!(); //~ ERROR `foo` is ambiguous macro_rules! m2 { () => { macro_rules! foo { () => {} } diff --git a/src/test/ui/macros/macro-shadowing.stderr b/src/test/ui/macros/macro-shadowing.stderr index 28f09509a62..d996f3a7041 100644 --- a/src/test/ui/macros/macro-shadowing.stderr +++ b/src/test/ui/macros/macro-shadowing.stderr @@ -9,16 +9,27 @@ LL | m1!(); | = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) -error: `foo` is already in scope +error[E0659]: `foo` is ambiguous + --> $DIR/macro-shadowing.rs:27:1 + | +LL | foo!(); //~ ERROR `foo` is ambiguous + | ^^^ ambiguous name + | +note: `foo` could refer to the name defined here --> $DIR/macro-shadowing.rs:20:5 | -LL | macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope +LL | macro_rules! foo { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | m1!(); | ------ in this macro invocation +note: `foo` could also refer to the name defined here + --> $DIR/macro-shadowing.rs:15:1 | - = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560) +LL | macro_rules! foo { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: macro-expanded macros do not shadow error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/macros/restricted-shadowing-legacy.rs b/src/test/ui/macros/restricted-shadowing-legacy.rs new file mode 100644 index 00000000000..f5cac2dfbfb --- /dev/null +++ b/src/test/ui/macros/restricted-shadowing-legacy.rs @@ -0,0 +1,289 @@ +// Legend: +// `N` - number of combination, from 0 to 4*4*4=64 +// `Outer < Invoc` means that expansion that produced macro definition `Outer` +// is a strict ancestor of expansion that produced macro definition `Inner`. +// `>`, `=` and `Unordered` mean "strict descendant", "same" and +// "not in ordering relation" for parent expansions. +// `+` - possible configuration +// `-` - configuration impossible due to properties of partial ordering +// `-?` - configuration impossible due to block/scope syntax +// `+?` - configuration possible only with legacy scoping + +// N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible | +// 1 | < | < | < | + | +// 2 | < | < | = | - | +// 3 | < | < | > | - | +// 4 | < | < | Unordered | - | +// 5 | < | = | < | + | +// 6 | < | = | = | - | +// 7 | < | = | > | - | +// 8 | < | = | Unordered | - | +// 9 | < | > | < | + | +// 10 | < | > | = | + | +// 11 | < | > | > | -? | +// 12 | < | > | Unordered | -? | +// 13 | < | Unordered | < | + | +// 14 | < | Unordered | = | - | +// 15 | < | Unordered | > | - | +// 16 | < | Unordered | Unordered | -? | +// 17 | = | < | < | + | +// 18 | = | < | = | - | +// 19 | = | < | > | - | +// 20 | = | < | Unordered | - | +// 21 | = | = | < | - | +// 22 | = | = | = | + | +// 23 | = | = | > | - | +// 24 | = | = | Unordered | - | +// 25 | = | > | < | - | +// 26 | = | > | = | - | +// 27 | = | > | > | -? | +// 28 | = | > | Unordered | - | +// 29 | = | Unordered | < | - | +// 30 | = | Unordered | = | - | +// 31 | = | Unordered | > | - | +// 32 | = | Unordered | Unordered | -? | +// 33 | > | < | < | +? | +// 34 | > | < | = | +? | +// 35 | > | < | > | +? | +// 36 | > | < | Unordered | + | +// 37 | > | = | < | - | +// 38 | > | = | = | - | +// 39 | > | = | > | + | +// 40 | > | = | Unordered | - | +// 41 | > | > | < | - | +// 42 | > | > | = | - | +// 43 | > | > | > | -? | +// 44 | > | > | Unordered | - | +// 45 | > | Unordered | < | - | +// 46 | > | Unordered | = | - | +// 47 | > | Unordered | > | -? | +// 48 | > | Unordered | Unordered | -? | +// 49 | Unordered | < | < | -? | +// 50 | Unordered | < | = | - | +// 51 | Unordered | < | > | - | +// 52 | Unordered | < | Unordered | + | +// 53 | Unordered | = | < | - | +// 54 | Unordered | = | = | - | +// 55 | Unordered | = | > | - | +// 56 | Unordered | = | Unordered | + | +// 57 | Unordered | > | < | - | +// 58 | Unordered | > | = | - | +// 59 | Unordered | > | > | + | +// 60 | Unordered | > | Unordered | + | +// 61 | Unordered | Unordered | < | +? | +// 62 | Unordered | Unordered | = | +? | +// 63 | Unordered | Unordered | > | +? | +// 64 | Unordered | Unordered | Unordered | + | + +#![feature(decl_macro, rustc_attrs)] + +struct Right; +// struct Wrong; // not defined + +macro_rules! include { () => { + macro_rules! gen_outer { () => { + macro_rules! m { () => { Wrong } } + }} + macro_rules! gen_inner { () => { + macro_rules! m { () => { Right } } + }} + macro_rules! gen_invoc { () => { + m!() + }} + + // ----------------------------------------------------------- + + fn check1() { + macro_rules! m { () => {} } + + macro_rules! gen_gen_inner_invoc { () => { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + }} + gen_gen_inner_invoc!(); + } + + fn check5() { + macro_rules! m { () => { Wrong } } + + macro_rules! gen_inner_invoc { () => { + macro_rules! m { () => { Right } } + m!(); // OK + }} + gen_inner_invoc!(); + } + + fn check9() { + macro_rules! m { () => { Wrong } } + + macro_rules! gen_inner_gen_invoc { () => { + macro_rules! m { () => { Right } } + gen_invoc!(); // OK + }} + gen_inner_gen_invoc!(); + } + + fn check10() { + macro_rules! m { () => { Wrong } } + + macro_rules! m { () => { Right } } + + gen_invoc!(); // OK + } + + fn check13() { + macro_rules! m { () => {} } + + gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + fn check17() { + macro_rules! m { () => {} } + + gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check22() { + macro_rules! m { () => { Wrong } } + + macro_rules! m { () => { Right } } + + m!(); // OK + } + + fn check36() { + gen_outer!(); + + gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check39() { + gen_outer!(); + + macro_rules! m { () => { Right } } + + m!(); // OK + } + + fn check52() { + gen_outer!(); + + macro_rules! gen_gen_inner_invoc { () => { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + }} + gen_gen_inner_invoc!(); + } + + fn check56() { + gen_outer!(); + + macro_rules! gen_inner_invoc { () => { + macro_rules! m { () => { Right } } + m!(); // OK + }} + gen_inner_invoc!(); + } + + fn check59() { + gen_outer!(); + + macro_rules! m { () => { Right } } + + gen_invoc!(); // OK + } + + fn check60() { + gen_outer!(); + + macro_rules! gen_inner_gen_invoc { () => { + macro_rules! m { () => { Right } } + gen_invoc!(); // OK + }} + gen_inner_gen_invoc!(); + } + + fn check64() { + gen_outer!(); + + gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + // ----------------------------------------------------------- + // These configurations are only possible with legacy macro scoping + + fn check33() { + macro_rules! gen_outer_gen_inner { () => { + macro_rules! m { () => {} } + gen_inner!(); + }} + gen_outer_gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check34() { + macro_rules! gen_outer_inner { () => { + macro_rules! m { () => { Wrong } } + macro_rules! m { () => { Right } } + }} + gen_outer_inner!(); + + m!(); // OK + } + + fn check35() { + macro_rules! gen_gen_outer_inner { () => { + gen_outer!(); + macro_rules! m { () => { Right } } + }} + gen_gen_outer_inner!(); + + m!(); // OK + } + + fn check61() { + macro_rules! gen_outer_gen_inner { () => { + macro_rules! m { () => {} } + gen_inner!(); + }} + gen_outer_gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + fn check62() { + macro_rules! gen_outer_inner { () => { + macro_rules! m { () => { Wrong } } + macro_rules! m { () => { Right } } + }} + gen_outer_inner!(); + + gen_invoc!(); // OK + } + + fn check63() { + macro_rules! gen_gen_outer_inner { () => { + gen_outer!(); + macro_rules! m { () => { Right } } + }} + gen_gen_outer_inner!(); + + gen_invoc!(); // OK + } +}} + +include!(); + +fn main() {} diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr new file mode 100644 index 00000000000..9e0d40c44b6 --- /dev/null +++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr @@ -0,0 +1,195 @@ +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:101:13 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:97:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:139:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:135:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:148:9 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:144:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:164:9 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:180:13 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:218:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:232:9 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:227:13 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:262:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-legacy.rs:257:13 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/macros/restricted-shadowing-modern.rs b/src/test/ui/macros/restricted-shadowing-modern.rs new file mode 100644 index 00000000000..448f623c220 --- /dev/null +++ b/src/test/ui/macros/restricted-shadowing-modern.rs @@ -0,0 +1,243 @@ +// Legend: +// `N` - number of combination, from 0 to 4*4*4=64 +// `Outer < Invoc` means that expansion that produced macro definition `Outer` +// is a strict ancestor of expansion that produced macro definition `Inner`. +// `>`, `=` and `Unordered` mean "strict descendant", "same" and +// "not in ordering relation" for parent expansions. +// `+` - possible configuration +// `-` - configuration impossible due to properties of partial ordering +// `-?` - configuration impossible due to block/scope syntax +// `+?` - configuration possible only with legacy scoping + +// N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible | +// 1 | < | < | < | + | +// 2 | < | < | = | - | +// 3 | < | < | > | - | +// 4 | < | < | Unordered | - | +// 5 | < | = | < | + | +// 6 | < | = | = | - | +// 7 | < | = | > | - | +// 8 | < | = | Unordered | - | +// 9 | < | > | < | + | +// 10 | < | > | = | + | +// 11 | < | > | > | -? | +// 12 | < | > | Unordered | -? | +// 13 | < | Unordered | < | + | +// 14 | < | Unordered | = | - | +// 15 | < | Unordered | > | - | +// 16 | < | Unordered | Unordered | -? | +// 17 | = | < | < | + | +// 18 | = | < | = | - | +// 19 | = | < | > | - | +// 20 | = | < | Unordered | - | +// 21 | = | = | < | - | +// 22 | = | = | = | + | +// 23 | = | = | > | - | +// 24 | = | = | Unordered | - | +// 25 | = | > | < | - | +// 26 | = | > | = | - | +// 27 | = | > | > | -? | +// 28 | = | > | Unordered | - | +// 29 | = | Unordered | < | - | +// 30 | = | Unordered | = | - | +// 31 | = | Unordered | > | - | +// 32 | = | Unordered | Unordered | -? | +// 33 | > | < | < | -? | +// 34 | > | < | = | -? | +// 35 | > | < | > | -? | +// 36 | > | < | Unordered | + | +// 37 | > | = | < | - | +// 38 | > | = | = | - | +// 39 | > | = | > | + | +// 40 | > | = | Unordered | - | +// 41 | > | > | < | - | +// 42 | > | > | = | - | +// 43 | > | > | > | -? | +// 44 | > | > | Unordered | - | +// 45 | > | Unordered | < | - | +// 46 | > | Unordered | = | - | +// 47 | > | Unordered | > | -? | +// 48 | > | Unordered | Unordered | -? | +// 49 | Unordered | < | < | -? | +// 50 | Unordered | < | = | - | +// 51 | Unordered | < | > | - | +// 52 | Unordered | < | Unordered | + | +// 53 | Unordered | = | < | - | +// 54 | Unordered | = | = | - | +// 55 | Unordered | = | > | - | +// 56 | Unordered | = | Unordered | + | +// 57 | Unordered | > | < | - | +// 58 | Unordered | > | = | - | +// 59 | Unordered | > | > | + | +// 60 | Unordered | > | Unordered | + | +// 61 | Unordered | Unordered | < | -? | +// 62 | Unordered | Unordered | = | -? | +// 63 | Unordered | Unordered | > | -? | +// 64 | Unordered | Unordered | Unordered | + | + +#![feature(decl_macro, rustc_attrs)] + +struct Right; +// struct Wrong; // not defined + +#[rustc_transparent_macro] +macro include() { + #[rustc_transparent_macro] + macro gen_outer() { + macro m() { Wrong } + } + #[rustc_transparent_macro] + macro gen_inner() { + macro m() { Right } + } + #[rustc_transparent_macro] + macro gen_invoc() { + m!() + } + + // ----------------------------------------------------------- + + fn check1() { + macro m() {} + { + #[rustc_transparent_macro] + macro gen_gen_inner_invoc() { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + gen_gen_inner_invoc!(); + } + } + + fn check5() { + macro m() { Wrong } + { + #[rustc_transparent_macro] + macro gen_inner_invoc() { + macro m() { Right } + m!(); // OK + } + gen_inner_invoc!(); + } + } + + fn check9() { + macro m() { Wrong } + { + #[rustc_transparent_macro] + macro gen_inner_gen_invoc() { + macro m() { Right } + gen_invoc!(); // OK + } + gen_inner_gen_invoc!(); + } + } + + fn check10() { + macro m() { Wrong } + { + macro m() { Right } + gen_invoc!(); // OK + } + } + + fn check13() { + macro m() {} + { + gen_inner!(); + #[rustc_transparent_macro] + macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + } + + fn check17() { + macro m() {} + { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + } + + fn check22() { + macro m() { Wrong } + { + macro m() { Right } + m!(); // OK + } + } + + fn check36() { + gen_outer!(); + { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + } + + fn check39() { + gen_outer!(); + { + macro m() { Right } + m!(); // OK + } + } + + fn check52() { + gen_outer!(); + { + #[rustc_transparent_macro] + macro gen_gen_inner_invoc() { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + gen_gen_inner_invoc!(); + } + } + + fn check56() { + gen_outer!(); + { + #[rustc_transparent_macro] + macro gen_inner_invoc() { + macro m() { Right } + m!(); // OK + } + gen_inner_invoc!(); + } + } + + fn check59() { + gen_outer!(); + { + macro m() { Right } + gen_invoc!(); // OK + } + } + + fn check60() { + gen_outer!(); + { + #[rustc_transparent_macro] + macro gen_inner_gen_invoc() { + macro m() { Right } + gen_invoc!(); // OK + } + gen_inner_gen_invoc!(); + } + } + + fn check64() { + gen_outer!(); + { + gen_inner!(); + #[rustc_transparent_macro] + macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + } +} + +include!(); + +fn main() {} diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr new file mode 100644 index 00000000000..0462438be78 --- /dev/null +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -0,0 +1,147 @@ +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:106:17 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:101:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:149:33 + | +LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:145:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:158:13 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:155:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:174:13 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:192:17 + | +LL | m!(); //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:235:33 + | +LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + | ^ ambiguous name + | +note: `m` could refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation +note: `m` could also refer to the name defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ----------- in this macro invocation + = note: macro-expanded macros do not shadow + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/out-of-order-shadowing.rs b/src/test/ui/out-of-order-shadowing.rs index 1fafaf85112..977b475b113 100644 --- a/src/test/ui/out-of-order-shadowing.rs +++ b/src/test/ui/out-of-order-shadowing.rs @@ -9,11 +9,10 @@ // except according to those terms. // aux-build:define_macro.rs -// error-pattern: `bar` is already in scope macro_rules! bar { () => {} } define_macro!(bar); -bar!(); +bar!(); //~ ERROR `bar` is ambiguous macro_rules! m { () => { #[macro_use] extern crate define_macro; } } m!(); diff --git a/src/test/ui/out-of-order-shadowing.stderr b/src/test/ui/out-of-order-shadowing.stderr index 78e32e23ff6..d96a802cb3f 100644 --- a/src/test/ui/out-of-order-shadowing.stderr +++ b/src/test/ui/out-of-order-shadowing.stderr @@ -1,11 +1,22 @@ -error: `bar` is already in scope +error[E0659]: `bar` is ambiguous --> $DIR/out-of-order-shadowing.rs:15:1 | +LL | bar!(); //~ ERROR `bar` is ambiguous + | ^^^ ambiguous name + | +note: `bar` could refer to the name defined here + --> $DIR/out-of-order-shadowing.rs:14:1 + | LL | define_macro!(bar); | ^^^^^^^^^^^^^^^^^^^ +note: `bar` could also refer to the name defined here + --> $DIR/out-of-order-shadowing.rs:13:1 | - = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560) +LL | macro_rules! bar { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: macro-expanded macros do not shadow = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error +For more information about this error, try `rustc --explain E0659`. |
