diff --git a/src/Cargo.lock b/src/Cargo.lock index 5d9f84650470d..6a9488226b1bd 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2388,6 +2388,7 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "arena 0.0.0", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 4286b0628f5ff..5d9d4deb0abc9 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -36,6 +36,8 @@ pub enum NonMacroAttrKind { Tool, /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). DeriveHelper, + /// Single-segment custom attriubte registered by a legacy plugin (`register_attribute`). + LegacyPluginHelper, /// Single-segment custom attribute not registered in any way (`#[my_attr]`). Custom, } @@ -259,6 +261,7 @@ impl NonMacroAttrKind { NonMacroAttrKind::Builtin => "built-in attribute", NonMacroAttrKind::Tool => "tool attribute", NonMacroAttrKind::DeriveHelper => "derive helper attribute", + NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute", NonMacroAttrKind::Custom => "custom attribute", } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 23533b7a4c390..a4386c6cbfd43 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -1012,6 +1012,7 @@ impl_stable_hash_for!(enum hir::def::NonMacroAttrKind { Builtin, Tool, DeriveHelper, + LegacyPluginHelper, Custom, }); diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 837340f70fce7..3a8e84a3280c6 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["dylib"] test = false [dependencies] +bitflags = "1.0" log = "0.4" syntax = { path = "../libsyntax" } rustc = { path = "../librustc" } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ece0188fa626d..a93cc7ad7518a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -17,6 +17,8 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] +#[macro_use] +extern crate bitflags; #[macro_use] extern crate log; #[macro_use] @@ -1012,7 +1014,8 @@ pub struct ModuleData<'a> { normal_ancestor_id: DefId, resolutions: RefCell>>>, - legacy_macro_resolutions: RefCell, Option)>>, + legacy_macro_resolutions: RefCell, + Option<&'a NameBinding<'a>>)>>, macro_resolutions: RefCell, Span)>>, builtin_attrs: RefCell)>>, @@ -1210,10 +1213,6 @@ impl<'a> NameBinding<'a> { } } - fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc { - resolver.get_macro(self.def_ignoring_ambiguity()) - } - // We sometimes need to treat variants as `pub` for backwards compatibility fn pseudo_vis(&self) -> ty::Visibility { if self.is_variant() && self.def().def_id().is_local() { @@ -3664,8 +3663,8 @@ 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, None, parent_scope, record_used, - record_used, path_span).map(|(b, _)| b) + self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope, + record_used, record_used, path_span) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ff6e8a96f30ba..c31b558dedea0 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -11,7 +11,7 @@ use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error}; use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; use ModuleOrUniformRoot; -use Namespace::{self, TypeNS, MacroNS}; +use Namespace::{self, *}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, @@ -22,9 +22,9 @@ use rustc::{ty, lint}; use syntax::ast::{self, Name, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; -use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; +use syntax::ext::base::{self, Determinacy}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; -use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith}; +use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, Mark}; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue}; @@ -43,9 +43,6 @@ use std::cell::Cell; use std::mem; use rustc_data_structures::sync::Lrc; -#[derive(Clone, Copy)] -crate struct FromPrelude(bool); - #[derive(Clone)] pub struct InvocationData<'a> { def_index: DefIndex, @@ -245,27 +242,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { // Resolves attribute and derive legacy macros from `#![plugin(..)]`. fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) -> Option { - for i in 0..attrs.len() { - let name = attrs[i].name(); - - if self.session.plugin_attributes.borrow().iter() - .any(|&(ref attr_nm, _)| name == &**attr_nm) { - attr::mark_known(&attrs[i]); - } - - match self.builtin_macros.get(&name).cloned() { - Some(binding) => match *binding.get_macro(self) { - MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { - return Some(attrs.remove(i)) - } - _ => {} - }, - None => {} - } + if !allow_derive { + return None; } - if !allow_derive { return None } - // Check for legacy derives for i in 0..attrs.len() { let name = attrs[i].name(); @@ -333,29 +313,24 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy> { - let (path, kind, derives_in_scope, together_with) = match invoc.kind { + let (path, kind, derives_in_scope, after_derive) = match invoc.kind { InvocationKind::Attr { attr: None, .. } => return Ok(None), - InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } => - (&attr.path, MacroKind::Attr, traits.clone(), together_with), + InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } => + (&attr.path, MacroKind::Attr, traits.clone(), after_derive), InvocationKind::Bang { ref mac, .. } => - (&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None), + (&mac.node.path, MacroKind::Bang, Vec::new(), false), InvocationKind::Derive { ref path, .. } => - (path, MacroKind::Derive, Vec::new(), TogetherWith::None), + (path, MacroKind::Derive, Vec::new(), false), }; let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?; if let Def::Macro(def_id, _) = def { - match together_with { - TogetherWith::Derive => - self.session.span_err(invoc.span(), - "macro attributes must be placed before `#[derive]`"), - TogetherWith::TestBench if !self.session.features_untracked().plugin => - self.session.span_err(invoc.span(), - "macro attributes cannot be used together with `#[test]` or `#[bench]`"), - _ => {} + if after_derive { + self.session.span_err(invoc.span(), + "macro attributes must be placed before `#[derive]`"); } self.macro_defs.insert(invoc.expansion_data.mark, def_id); let normal_module_def_id = @@ -520,37 +495,34 @@ impl<'a, 'cl> Resolver<'a, 'cl> { Err(Determinacy::Determined) }, }; + parent_scope.module.macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); - return def; - } - let result = if let Some(legacy_binding) = self.resolve_legacy_scope(path[0], Some(kind), - parent_scope, false) { - Ok(legacy_binding.def()) + def } else { - match self.resolve_lexical_macro_path_segment(path[0], MacroNS, Some(kind), - parent_scope, false, force, span) { - Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()), + let binding = self.early_resolve_ident_in_lexical_scope( + path[0], MacroNS, Some(kind), parent_scope, false, force, span + ); + match binding { + Ok(..) => {} + Err(Determinacy::Determined) => self.found_unresolved_macro = true, Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), - Err(Determinacy::Determined) => { - self.found_unresolved_macro = true; - Err(Determinacy::Determined) - } } - }; - parent_scope.module.legacy_macro_resolutions.borrow_mut() - .push((path[0], kind, parent_scope.clone(), result.ok())); + parent_scope.module.legacy_macro_resolutions.borrow_mut() + .push((path[0], kind, parent_scope.clone(), binding.ok())); - result + binding.map(|binding| binding.def_ignoring_ambiguity()) + } } - // Resolve the initial segment of a non-global macro path - // (e.g. `foo` in `foo::bar!(); or `foo!();`). + // Resolve an identifier in lexical scope. // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during // expansion and import resolution (perhaps they can be merged in the future). - crate fn resolve_lexical_macro_path_segment( + // The function is used for resolving initial segments of macro paths (e.g. `foo` in + // `foo::bar!(); or `foo!();`) and can be used for "uniform path" imports in the future. + crate fn early_resolve_ident_in_lexical_scope( &mut self, mut ident: Ident, ns: Namespace, @@ -559,12 +531,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { record_used: bool, force: bool, path_span: Span, - ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> { + ) -> Result<&'a NameBinding<'a>, Determinacy> { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names // built into the language or standard library. This way we can add new names into the // language or standard library without breaking user code. - // 2. "Closed set" below means new names can appear after the current resolution attempt. + // 2. "Closed set" below means new names cannot appear after the current resolution attempt. // Places to search (in order of decreasing priority): // (Type NS) // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet @@ -575,24 +547,58 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 4. Tool modules (closed, controlled right now, but not in the future). // 5. Standard library prelude (de-facto closed, controlled). // 6. Language prelude (closed, controlled). + // (Value NS) + // 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet + // (open set, not controlled). + // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). + // 3. Standard library prelude (de-facto closed, controlled). // (Macro NS) - // 0. Derive helpers (open, not controlled). All ambiguities with other names + // 1-3. Derive helpers (open, not controlled). All ambiguities with other names // are currently reported as errors. They should be higher in priority than preludes // and probably even names in modules according to the "general principles" above. They // also should be subject to restricted shadowing because are effectively produced by // derives (you need to resolve the derive first to add helpers into scope), but they // should be available before the derive is expanded for compatibility. // It's mess in general, so we are being conservative for now. - // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents - // (open, not controlled). - // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled). - // 2a. User-defined prelude from macro-use + // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher + // priority than prelude macros, but create ambiguities with macros in modules. + // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). Have higher priority than prelude macros, but create + // ambiguities with `macro_rules`. + // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled). + // 4a. User-defined prelude from macro-use // (open, the open part is from macro expansions, not controlled). - // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) - // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins). - // 4. Language prelude: builtin attributes (closed, controlled). + // 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) + // 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins). + // 6. Language prelude: builtin attributes (closed, controlled). + // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers, + // but introduced by legacy plugins using `register_attribute`. Priority is somewhere + // in prelude, not sure where exactly (creates ambiguities with any other prelude names). + + enum WhereToResolve<'a> { + DeriveHelpers, + MacroRules(LegacyScope<'a>), + Module(Module<'a>), + MacroUsePrelude, + BuiltinMacros, + BuiltinAttrs, + LegacyPluginHelpers, + ExternPrelude, + ToolPrelude, + StdLibPrelude, + BuiltinTypes, + } + + bitflags! { + struct Flags: u8 { + const DERIVE_HELPERS = 1 << 0; + const MACRO_RULES = 1 << 1; + const MODULE = 1 << 2; + const PRELUDE = 1 << 3; + } + } - assert!(ns == TypeNS || ns == MacroNS); assert!(force || !record_used); // `record_used` implies `force` ident = ident.modern(); @@ -607,25 +613,38 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // } // 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>), - MacroUsePrelude, - BuiltinMacros, - BuiltinAttrs, - DeriveHelpers, - ExternPrelude, - ToolPrelude, - StdLibPrelude, - BuiltinTypes, - } + let mut innermost_result: Option<(&NameBinding, Flags, /* conflicts with */ Flags)> = None; // Go through all the scopes and try to resolve the name. let mut where_to_resolve = WhereToResolve::DeriveHelpers; let mut use_prelude = !parent_scope.module.no_implicit_prelude; loop { let result = match where_to_resolve { + WhereToResolve::DeriveHelpers => { + let mut result = Err(Determinacy::Determined); + for derive in &parent_scope.derives { + let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; + if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive, + &parent_scope, force) { + if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext { + if helper_attrs.contains(&ident.name) { + let binding = + (Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, derive.span, Mark::root()) + .to_name_binding(self.arenas); + result = Ok((binding, Flags::DERIVE_HELPERS, Flags::all())); + break; + } + } + } + } + result + } + WhereToResolve::MacroRules(legacy_scope) => match legacy_scope { + LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => + Ok((legacy_binding.binding, Flags::MACRO_RULES, Flags::empty())), + _ => Err(Determinacy::Determined), + } WhereToResolve::Module(module) => { let orig_current_module = mem::replace(&mut self.current_module, module); let binding = self.resolve_ident_in_module_unadjusted( @@ -637,17 +656,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> { path_span, ); self.current_module = orig_current_module; - binding.map(|binding| (binding, FromPrelude(false))) + binding.map(|binding| (binding, Flags::MODULE, Flags::empty())) } WhereToResolve::MacroUsePrelude => { match self.macro_use_prelude.get(&ident.name).cloned() { - Some(binding) => Ok((binding, FromPrelude(true))), + Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())), None => Err(Determinacy::Determined), } } WhereToResolve::BuiltinMacros => { match self.builtin_macros.get(&ident.name).cloned() { - Some(binding) => Ok((binding, FromPrelude(true))), + Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())), None => Err(Determinacy::Determined), } } @@ -656,30 +675,21 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin), ty::Visibility::Public, ident.span, Mark::root()) .to_name_binding(self.arenas); - Ok((binding, FromPrelude(true))) + Ok((binding, Flags::PRELUDE, Flags::empty())) } else { Err(Determinacy::Determined) } } - WhereToResolve::DeriveHelpers => { - let mut result = Err(Determinacy::Determined); - for derive in &parent_scope.derives { - let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; - if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive, - &parent_scope, force) { - if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext { - if helper_attrs.contains(&ident.name) { - let binding = - (Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - ty::Visibility::Public, derive.span, Mark::root()) - .to_name_binding(self.arenas); - result = Ok((binding, FromPrelude(false))); - break; - } - } - } + WhereToResolve::LegacyPluginHelpers => { + if self.session.plugin_attributes.borrow().iter() + .any(|(name, _)| ident.name == &**name) { + let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper), + ty::Visibility::Public, ident.span, Mark::root()) + .to_name_binding(self.arenas); + Ok((binding, Flags::PRELUDE, Flags::PRELUDE)) + } else { + Err(Determinacy::Determined) } - result } WhereToResolve::ExternPrelude => { if use_prelude && self.session.extern_prelude.contains(&ident.name) { @@ -691,7 +701,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); - Ok((binding, FromPrelude(true))) + Ok((binding, Flags::PRELUDE, Flags::empty())) } else { Err(Determinacy::Determined) } @@ -700,7 +710,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if use_prelude && is_known_tool(ident.name) { let binding = (Def::ToolMod, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); - Ok((binding, FromPrelude(true))) + Ok((binding, Flags::PRELUDE, Flags::empty())) } else { Err(Determinacy::Determined) } @@ -717,46 +727,60 @@ impl<'a, 'cl> Resolver<'a, 'cl> { false, path_span, ) { - result = Ok((binding, FromPrelude(true))); + result = Ok((binding, Flags::PRELUDE, Flags::empty())); } } } result } WhereToResolve::BuiltinTypes => { - if let Some(prim_ty) = - self.primitive_type_table.primitive_types.get(&ident.name).cloned() { - let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public, - ident.span, Mark::root()).to_name_binding(self.arenas); - Ok((binding, FromPrelude(true))) - } else { - Err(Determinacy::Determined) + match self.primitive_type_table.primitive_types.get(&ident.name).cloned() { + Some(prim_ty) => { + let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok((binding, Flags::PRELUDE, Flags::empty())) + } + None => Err(Determinacy::Determined) } } }; macro_rules! continue_search { () => { where_to_resolve = match where_to_resolve { + WhereToResolve::DeriveHelpers => + WhereToResolve::MacroRules(parent_scope.legacy), + WhereToResolve::MacroRules(legacy_scope) => match legacy_scope { + LegacyScope::Binding(binding) => + WhereToResolve::MacroRules(binding.parent_legacy_scope), + LegacyScope::Invocation(invocation) => + WhereToResolve::MacroRules(invocation.output_legacy_scope.get()), + LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), + LegacyScope::Uninitialized => unreachable!(), + } WhereToResolve::Module(module) => { match self.hygienic_lexical_parent(module, &mut ident.span) { Some(parent_module) => WhereToResolve::Module(parent_module), None => { use_prelude = !module.no_implicit_prelude; - if ns == MacroNS { - WhereToResolve::MacroUsePrelude - } else { - WhereToResolve::ExternPrelude + match ns { + TypeNS => WhereToResolve::ExternPrelude, + ValueNS => WhereToResolve::StdLibPrelude, + MacroNS => WhereToResolve::MacroUsePrelude, } } } } WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros, WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, - WhereToResolve::BuiltinAttrs => break, // nowhere else to search - WhereToResolve::DeriveHelpers => WhereToResolve::Module(parent_scope.module), + WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers, + WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, - WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes, + WhereToResolve::StdLibPrelude => match ns { + TypeNS => WhereToResolve::BuiltinTypes, + ValueNS => break, // nowhere else to search + MacroNS => unreachable!(), + } WhereToResolve::BuiltinTypes => break, // nowhere else to search }; @@ -764,33 +788,36 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }} match result { - Ok(result) => { - if sub_namespace_mismatch(kind, result.0.macro_kind()) { + Ok((binding, flags, ambig_flags)) => { + if sub_namespace_mismatch(kind, binding.macro_kind()) { continue_search!(); } if !record_used { - return Ok(result); + return Ok(binding); } - if let Some(innermost_result) = innermost_result { + if let Some((innermost_binding, innermost_flags, innermost_ambig_flags)) + = innermost_result { // Found another solution, if the first one was "weak", report an error. - let (def, innermost_def) = (result.0.def(), innermost_result.0.def()); - if def != innermost_def && - (innermost_result.0.is_glob_import() || - innermost_result.0.may_appear_after(parent_scope.expansion, result.0) || - innermost_def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper) || - def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)) { + if binding.def() != innermost_binding.def() && + (innermost_binding.is_glob_import() || + innermost_binding.may_appear_after(parent_scope.expansion, binding) || + innermost_flags.intersects(ambig_flags) || + flags.intersects(innermost_ambig_flags) || + (innermost_flags.contains(Flags::MACRO_RULES) && + flags.contains(Flags::MODULE) && + !self.disambiguate_legacy_vs_modern(innermost_binding, binding))) { self.ambiguity_errors.push(AmbiguityError { ident, - b1: innermost_result.0, - b2: result.0, + b1: innermost_binding, + b2: binding, }); - return Ok(innermost_result); + return Ok(innermost_binding); } } else { // Found the first solution. - innermost_result = Some(result); + innermost_result = Some((binding, flags, ambig_flags)); } continue_search!(); @@ -803,8 +830,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } // The first found solution was the only one, return it. - if let Some(innermost_result) = innermost_result { - return Ok(innermost_result); + if let Some((binding, ..)) = innermost_result { + return Ok(binding); } let determinacy = Determinacy::determined(force); @@ -816,92 +843,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom), ty::Visibility::Public, ident.span, Mark::root()) .to_name_binding(self.arenas); - Ok((binding, FromPrelude(true))) + Ok(binding) } else { Err(determinacy) } } - fn resolve_legacy_scope( - &mut self, - ident: Ident, - kind: Option, - parent_scope: &ParentScope<'a>, - record_used: bool, - ) -> Option<&'a NameBinding<'a>> { - if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) { - return None; - } - - let ident = ident.modern(); - - // 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 = parent_scope.legacy; - loop { - 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(parent_scope.expansion, 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!(); - } - } - } - - // 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) { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { @@ -916,80 +863,52 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let legacy_macro_resolutions = mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new()); - for (ident, kind, parent_scope, def) in legacy_macro_resolutions { - let span = ident.span; - let legacy_resolution = self.resolve_legacy_scope( - ident, Some(kind), &parent_scope, true + for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions { + let binding = self.early_resolve_ident_in_lexical_scope( + ident, MacroNS, Some(kind), &parent_scope, true, true, ident.span ); - let resolution = self.resolve_lexical_macro_path_segment( - ident, MacroNS, Some(kind), &parent_scope, true, true, span - ); - - let check_consistency = |this: &Self, new_def: Def| { - if let Some(def) = def { - 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. - span_bug!(span, "inconsistent resolution for a macro"); + match binding { + Ok(binding) => { + let def = binding.def_ignoring_ambiguity(); + if let Some(initial_binding) = initial_binding { + self.record_use(ident, MacroNS, initial_binding); + let initial_def = initial_binding.def_ignoring_ambiguity(); + if self.ambiguity_errors.is_empty() && + def != initial_def && 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 a bug. + span_bug!(ident.span, "inconsistent resolution for a macro"); + } + } else { + // It's possible that the macro was unresolved (indeterminate) and silently + // expanded into a dummy fragment for recovery during expansion. + // Now, post-expansion, the resolution may succeed, but we can't change the + // past and need to report an error. + let msg = format!("cannot determine resolution for the {} `{}`", + kind.descr(), ident); + let msg_note = "import resolution is stuck, try simplifying macro imports"; + self.session.struct_span_err(ident.span, &msg).note(msg_note).emit(); } - } else { - // It's possible that the macro was unresolved (indeterminate) and silently - // expanded into a dummy fragment for recovery during expansion. - // Now, post-expansion, the resolution may succeed, but we can't change the - // past and need to report an error. - let msg = - format!("cannot determine resolution for the {} `{}`", kind.descr(), ident); - let msg_note = "import resolution is stuck, try simplifying macro imports"; - this.session.struct_span_err(span, &msg).note(msg_note).emit(); } - }; - - match (legacy_resolution, resolution) { - (None, Err(_)) => { - assert!(def.is_none()); + Err(..) => { + assert!(initial_binding.is_none()); let bang = if kind == MacroKind::Bang { "!" } else { "" }; let msg = format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang); - let mut err = self.session.struct_span_err(span, &msg); - self.suggest_macro_name(&ident.as_str(), kind, &mut err, span); + let mut err = self.session.struct_span_err(ident.span, &msg); + self.suggest_macro_name(&ident.as_str(), kind, &mut err, ident.span); err.emit(); - }, - (Some(legacy_binding), Ok((binding, FromPrelude(from_prelude)))) - if legacy_binding.def() != binding.def_ignoring_ambiguity() && - (!from_prelude && - !self.disambiguate_legacy_vs_modern(legacy_binding, binding) || - legacy_binding.may_appear_after(parent_scope.expansion, binding)) => { - self.report_ambiguity_error(ident, legacy_binding, binding); - }, - // OK, non-macro-expanded legacy wins over prelude even if defs are different - // Also, non-macro-expanded legacy wins over modern from the same module - // Also, legacy and modern can co-exist if their defs are same - (Some(legacy_binding), Ok(_)) | - // OK, unambiguous resolution - (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); - } } - }; + } } let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new()); for (ident, parent_scope) in builtin_attrs { - let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope( - ident, Some(MacroKind::Attr), &parent_scope, true - ); - let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment( + let binding = self.early_resolve_ident_in_lexical_scope( ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span - ).map(|(binding, _)| binding).ok(); - - if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) { + ); + if let Ok(binding) = binding { if binding.def_ignoring_ambiguity() != Def::NonMacroAttr(NonMacroAttrKind::Builtin) { let builtin_binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin), diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 333131398151a..6e9877b1ab66d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -334,7 +334,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { // expansion. With restricted shadowing names from globs and macro expansions cannot // shadow names from outer scopes, so we can freely fallback from module search to search // in outer scopes. To continue search in outer scopes we have to lie a bit and return - // `Determined` to `resolve_lexical_macro_path_segment` even if the correct answer + // `Determined` to `early_resolve_ident_in_lexical_scope` even if the correct answer // for in-module resolution could be `Undetermined`. if restricted_shadowing { return Err(Determined); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 52322e98d46f9..e6e34dc8569ee 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -220,14 +220,6 @@ pub struct Invocation { pub expansion_data: ExpansionData, } -// Needed for feature-gating attributes used after derives or together with test/bench -#[derive(Clone, Copy, PartialEq)] -pub enum TogetherWith { - None, - Derive, - TestBench, -} - pub enum InvocationKind { Bang { mac: ast::Mac, @@ -238,7 +230,8 @@ pub enum InvocationKind { attr: Option, traits: Vec, item: Annotatable, - together_with: TogetherWith, + // We temporarily report errors for attribute macros placed after derives + after_derive: bool, }, Derive { path: Path, @@ -1084,19 +1077,17 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { traits: Vec, item: Annotatable, kind: AstFragmentKind, - together_with: TogetherWith) + after_derive: bool) -> AstFragment { - self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with }) + self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive }) } - fn find_attr_invoc(&self, attrs: &mut Vec, together_with: &mut TogetherWith) + fn find_attr_invoc(&self, attrs: &mut Vec, after_derive: &mut bool) -> Option { let attr = attrs.iter() .position(|a| { if a.path == "derive" { - *together_with = TogetherWith::Derive - } else if a.path == "rustc_test_marker2" { - *together_with = TogetherWith::TestBench + *after_derive = true; } !attr::is_known(a) && !is_builtin_attr(a) }) @@ -1109,19 +1100,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { "non-builtin inner attributes are unstable"); } } - if together_with == &TogetherWith::None && - attrs.iter().any(|a| a.path == "rustc_test_marker2") { - *together_with = TogetherWith::TestBench; - } attr } /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. fn classify_item(&mut self, mut item: T) - -> (Option, Vec, T, TogetherWith) + -> (Option, Vec, T, /* after_derive */ bool) where T: HasAttrs, { - let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None); + let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item = item.map_attrs(|mut attrs| { if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, @@ -1130,20 +1117,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { return attrs; } - attr = self.find_attr_invoc(&mut attrs, &mut together_with); + attr = self.find_attr_invoc(&mut attrs, &mut after_derive); traits = collect_derives(&mut self.cx, &mut attrs); attrs }); - (attr, traits, item, together_with) + (attr, traits, item, after_derive) } /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough /// to the unused-attributes lint (making it an error on statements and expressions /// is a breaking change) fn classify_nonitem(&mut self, mut item: T) - -> (Option, T, TogetherWith) { - let (mut attr, mut together_with) = (None, TogetherWith::None); + -> (Option, T, /* after_derive */ bool) { + let (mut attr, mut after_derive) = (None, false); item = item.map_attrs(|mut attrs| { if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, @@ -1152,11 +1139,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { return attrs; } - attr = self.find_attr_invoc(&mut attrs, &mut together_with); + attr = self.find_attr_invoc(&mut attrs, &mut after_derive); attrs }); - (attr, item, together_with) + (attr, item, after_derive) } fn configure(&mut self, node: T) -> Option { @@ -1195,7 +1182,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { expr.node = self.cfg.configure_expr_kind(expr.node); // ignore derives so they remain unused - let (attr, expr, together_with) = self.classify_nonitem(expr); + let (attr, expr, after_derive) = self.classify_nonitem(expr); if attr.is_some() { // collect the invoc regardless of whether or not attributes are permitted here @@ -1204,7 +1191,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { // AstFragmentKind::Expr requires the macro to emit an expression return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, together_with).make_expr(); + AstFragmentKind::Expr, after_derive).make_expr(); } if let ast::ExprKind::Mac(mac) = expr.node { @@ -1220,13 +1207,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { expr.node = self.cfg.configure_expr_kind(expr.node); // ignore derives so they remain unused - let (attr, expr, together_with) = self.classify_nonitem(expr); + let (attr, expr, after_derive) = self.classify_nonitem(expr); if attr.is_some() { attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, together_with).make_opt_expr(); + AstFragmentKind::OptExpr, after_derive).make_opt_expr(); } if let ast::ExprKind::Mac(mac) = expr.node { @@ -1258,18 +1245,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { - let (attr, derives, stmt_, together_with) = if stmt.is_item() { + let (attr, derives, stmt_, after_derive) = if stmt.is_item() { self.classify_item(stmt) } else { // ignore derives on non-item statements so it falls through // to the unused-attributes lint - let (attr, stmt, together_with) = self.classify_nonitem(stmt); - (attr, vec![], stmt, together_with) + let (attr, stmt, after_derive) = self.classify_nonitem(stmt); + (attr, vec![], stmt, after_derive) }; if attr.is_some() || !derives.is_empty() { return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)), - AstFragmentKind::Stmts, together_with).make_stmts(); + AstFragmentKind::Stmts, after_derive).make_stmts(); } stmt = stmt_; @@ -1311,10 +1298,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_item(&mut self, item: P) -> SmallVec<[P; 1]> { let item = configure!(self, item); - let (attr, traits, item, together_with) = self.classify_item(item); + let (attr, traits, item, after_derive) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { return self.collect_attr(attr, traits, Annotatable::Item(item), - AstFragmentKind::Items, together_with).make_items(); + AstFragmentKind::Items, after_derive).make_items(); } match item.node { @@ -1386,10 +1373,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { let item = configure!(self, item); - let (attr, traits, item, together_with) = self.classify_item(item); + let (attr, traits, item, after_derive) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)), - AstFragmentKind::TraitItems, together_with).make_trait_items() + AstFragmentKind::TraitItems, after_derive).make_trait_items() } match item.node { @@ -1405,10 +1392,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { let item = configure!(self, item); - let (attr, traits, item, together_with) = self.classify_item(item); + let (attr, traits, item, after_derive) = self.classify_item(item); if attr.is_some() || !traits.is_empty() { return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)), - AstFragmentKind::ImplItems, together_with).make_impl_items(); + AstFragmentKind::ImplItems, after_derive).make_impl_items(); } match item.node { @@ -1440,11 +1427,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> { - let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item); + let (attr, traits, foreign_item, after_derive) = self.classify_item(foreign_item); if attr.is_some() || !traits.is_empty() { return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)), - AstFragmentKind::ForeignItems, together_with) + AstFragmentKind::ForeignItems, after_derive) .make_foreign_items(); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index adbe2f9d4393f..0cc3ef60cee9a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -990,10 +990,6 @@ 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_test_marker2", Normal, Gated(Stability::Unstable, - "rustc_attrs", - "temporarily used by rustc to report some errors", - cfg_fn!(rustc_attrs))), ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "used internally for testing macro hygiene", diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 8ddfb1d9cba22..be3485cfa7cc2 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -49,7 +49,7 @@ pub fn expand_test_or_bench( // If we're not in test configuration, remove the annotated item if !cx.ecfg.should_test { return vec![]; } - let mut item = + let item = if let Annotatable::Item(i) = item { i } else { cx.parse_sess.span_diagnostic.span_fatal(item.span(), @@ -192,12 +192,6 @@ pub fn expand_test_or_bench( debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); - // Temporarily add another marker to the original item for error reporting - let marker2 = cx.attribute( - attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2")) - ); - item.attrs.push(marker2); - vec![ // Access to libtest under a gensymed name Annotatable::Item(test_extern), diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index c3e7787cf7f30..f51a6aae068a1 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -19,8 +19,8 @@ #[macro_use] #[no_link] extern crate macro_crate_test; -#[derive(PartialEq, Clone, Debug)] #[rustc_into_multi_foo] +#[derive(PartialEq, Clone, Debug)] fn foo() -> AnotherFakeTypeThatHadBetterGoAway {} // Check that the `#[into_multi_foo]`-generated `foo2` is configured away diff --git a/src/test/ui-fulldeps/attribute-order-restricted.rs b/src/test/ui-fulldeps/attribute-order-restricted.rs index 553cd86e62038..7b1eecd155865 100644 --- a/src/test/ui-fulldeps/attribute-order-restricted.rs +++ b/src/test/ui-fulldeps/attribute-order-restricted.rs @@ -1,9 +1,5 @@ // aux-build:attr_proc_macro.rs -// compile-flags:--test -#![feature(test)] - -extern crate test; extern crate attr_proc_macro; use attr_proc_macro::*; @@ -15,18 +11,4 @@ struct Before; #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]` struct After; -#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` -#[test] -fn test_before() {} - -#[test] -#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` -fn test_after() {} - -#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` -#[bench] -fn bench_before(b: &mut test::Bencher) {} - -#[bench] -#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` -fn bench_after(b: &mut test::Bencher) {} +fn main() {} diff --git a/src/test/ui-fulldeps/attribute-order-restricted.stderr b/src/test/ui-fulldeps/attribute-order-restricted.stderr index 841fc630b2270..a4f165cd1b52c 100644 --- a/src/test/ui-fulldeps/attribute-order-restricted.stderr +++ b/src/test/ui-fulldeps/attribute-order-restricted.stderr @@ -1,32 +1,8 @@ error: macro attributes must be placed before `#[derive]` - --> $DIR/attribute-order-restricted.rs:15:1 + --> $DIR/attribute-order-restricted.rs:11:1 | LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]` | ^^^^^^^^^^^^^^^^^^ -error: macro attributes cannot be used together with `#[test]` or `#[bench]` - --> $DIR/attribute-order-restricted.rs:18:1 - | -LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` - | ^^^^^^^^^^^^^^^^^^ - -error: macro attributes cannot be used together with `#[test]` or `#[bench]` - --> $DIR/attribute-order-restricted.rs:23:1 - | -LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` - | ^^^^^^^^^^^^^^^^^^ - -error: macro attributes cannot be used together with `#[test]` or `#[bench]` - --> $DIR/attribute-order-restricted.rs:26:1 - | -LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` - | ^^^^^^^^^^^^^^^^^^ - -error: macro attributes cannot be used together with `#[test]` or `#[bench]` - --> $DIR/attribute-order-restricted.rs:31:1 - | -LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]` - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 5 previous errors +error: aborting due to previous error diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index e554bbb4f3146..7e5ab0c5abe07 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -1,20 +1,3 @@ -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 - | -LL | macro_rules! panic { () => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | } } -LL | m!(); - | ----- in this macro invocation - = note: `panic` is also a builtin macro - = note: macro-expanded macros do not shadow - error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:25:14 | @@ -43,6 +26,23 @@ LL | ::two_macros::m!(use foo::panic;); = note: `panic` is also a builtin macro = note: macro-expanded macro imports do not shadow +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 + | +LL | macro_rules! panic { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | } } +LL | m!(); + | ----- in this macro invocation + = note: `panic` is also a builtin macro + = note: macro-expanded macros do not shadow + error[E0659]: `n` is ambiguous --> $DIR/shadow_builtin_macros.rs:59:5 |