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, /// 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(..) | @@ -3483,6 +3496,20 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { record_used: bool, 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>, + path: &[Ident], + opt_ns: Option, // `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; @@ -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>, - pub def_index: DefIndex, - // The scope in which the invocation path is resolved. - pub legacy_scope: Cell>, - // The smallest scope that includes this invocation's expansion, - // or `Empty` if this invocation has not been expanded yet. - pub expansion: Cell>, + def_index: DefIndex, + /// Module in which the macro was invoked. + crate module: Cell>, + /// Legacy scope in which the macro was invoked. + /// The invocation path is resolved in this scope. + crate parent_legacy_scope: Cell>, + /// 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>, } 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>, - 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) { @@ -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 { 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>, - 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; - } - } - } - 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); - } - return Some((potential_binding, FromExpansion(relative_depth > 0))); - } - scope = &potential_binding.parent; - } + 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); + } + + 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); + } + } else { + // Found the first solution. + innermost_result = Some(result); + } + + 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 @@ -100,6 +100,11 @@ impl Mark { Mark(raw) } + #[inline] + pub fn parent(self) -> Mark { + HygieneData::with(|data| data.marks[self.0 as usize].parent) + } + #[inline] pub fn expn_info(self) -> Option { 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 + --> :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 or the MIT license +// , 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`.