diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4a63311c48a6f..c79a4a93f2708 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -80,7 +80,7 @@ use std::mem::replace; use rustc_data_structures::sync::Lrc; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; -use macros::{InvocationData, LegacyBinding, MacroBinding}; +use macros::{InvocationData, LegacyBinding}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -1399,7 +1399,7 @@ 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>, @@ -3529,7 +3529,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } 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(MacroBinding::binding) + false, path_span).map(|(b, _)| b) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; @@ -4431,6 +4431,42 @@ 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, + ) { + 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 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!("macro-expanded {} do not shadow", + if is_import1 { "macro imports" } else { "macros" }) + } else { + format!("macro-expanded {} do not shadow when used in a macro invocation path", + if is_import1 { "imports" } else { "items" }) + }) + } else if is_glob1 { + Some(format!("consider adding an explicit import of `{}` to disambiguate", name)) + } 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), + }; + if let Some(note) = note { + err.note(¬e); + } + err.emit(); + } + fn report_errors(&mut self, krate: &Crate) { self.report_shadowing_errors(); self.report_with_use_injections(krate); @@ -4446,30 +4482,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { - if !reported_spans.insert(span) { continue } - let participle = |binding: &NameBinding| { - if binding.is_import() { "imported" } else { "defined" } - }; - let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1)); - let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2)); - let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() { - format!("consider adding an explicit import of `{}` to disambiguate", name) - } else if let Def::Macro(..) = b1.def() { - format!("macro-expanded {} do not shadow", - if b1.is_import() { "macro imports" } else { "macros" }) - } else { - format!("macro-expanded {} do not shadow when used in a macro invocation path", - if b1.is_import() { "imports" } else { "items" }) - }; - - let mut err = struct_span_err!(self.session, span, E0659, "`{}` is 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", name)), - _ => err.span_note(b2.span, &msg2), - }; - err.note(¬e).emit(); + 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 &PrivacyError(span, name, binding) in &self.privacy_errors { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 8f2e76d8866dd..1161d57417b18 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -43,6 +43,9 @@ use std::cell::Cell; use std::mem; use rustc_data_structures::sync::Lrc; +crate struct FromPrelude(bool); +crate struct FromExpansion(bool); + #[derive(Clone)] pub struct InvocationData<'a> { pub module: Cell>, @@ -80,6 +83,12 @@ pub struct LegacyBinding<'a> { pub span: Span, } +impl<'a> LegacyBinding<'a> { + fn def(&self) -> Def { + Def::Macro(self.def_id, MacroKind::Bang) + } +} + pub struct ProcMacError { crate_name: Symbol, name: Symbol, @@ -88,37 +97,6 @@ pub struct ProcMacError { warn_msg: &'static str, } -#[derive(Copy, Clone)] -pub enum MacroBinding<'a> { - Legacy(&'a LegacyBinding<'a>), - Global(&'a NameBinding<'a>), - Modern(&'a NameBinding<'a>), -} - -impl<'a> MacroBinding<'a> { - pub fn span(self) -> Span { - match self { - MacroBinding::Legacy(binding) => binding.span, - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span, - } - } - - pub fn binding(self) -> &'a NameBinding<'a> { - match self { - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding, - MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"), - } - } - - pub fn def_ignoring_ambiguity(self) -> Def { - match self { - MacroBinding::Legacy(binding) => Def::Macro(binding.def_id, MacroKind::Bang), - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => - binding.def_ignoring_ambiguity(), - } - } -} - impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() @@ -319,94 +297,38 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { None } - fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool) - -> Result>, Determinacy> { - let def = match invoc.kind { - InvocationKind::Attr { attr: None, .. } => return Ok(None), - _ => self.resolve_invoc_to_def(invoc, scope, force)?, + fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool) + -> Result>, Determinacy> { + let (path, kind, derives_in_scope) = match invoc.kind { + InvocationKind::Attr { attr: None, .. } => + return Ok(None), + InvocationKind::Attr { attr: Some(ref attr), ref traits, .. } => + (&attr.path, MacroKind::Attr, &traits[..]), + InvocationKind::Bang { ref mac, .. } => + (&mac.node.path, MacroKind::Bang, &[][..]), + InvocationKind::Derive { ref path, .. } => + (path, MacroKind::Derive, &[][..]), }; - if let Def::Macro(_, MacroKind::ProcMacroStub) = def { - self.report_proc_macro_stub(invoc.span()); - return Err(Determinacy::Determined); - } else if let Def::NonMacroAttr(attr_kind) = def { - // Note that not only attributes, but anything in macro namespace can result in a - // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report the error - // below for these cases. - let is_attr_invoc = - if let InvocationKind::Attr { .. } = invoc.kind { true } else { false }; - let path = invoc.path().expect("no path for non-macro attr"); - match attr_kind { - NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper | - NonMacroAttrKind::Custom if is_attr_invoc => { - let features = self.session.features_untracked(); - if attr_kind == NonMacroAttrKind::Tool && - !features.tool_attributes { - feature_err(&self.session.parse_sess, "tool_attributes", - invoc.span(), GateIssue::Language, - "tool attributes are unstable").emit(); - } - if attr_kind == NonMacroAttrKind::Custom { - assert!(path.segments.len() == 1); - let name = path.segments[0].ident.name.as_str(); - if name.starts_with("rustc_") { - if !features.rustc_attrs { - let msg = "unless otherwise specified, attributes with the prefix \ - `rustc_` are reserved for internal compiler diagnostics"; - feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(), - GateIssue::Language, &msg).emit(); - } - } else if name.starts_with("derive_") { - if !features.custom_derive { - feature_err(&self.session.parse_sess, "custom_derive", invoc.span(), - GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit(); - } - } else if !features.custom_attribute { - let msg = format!("The attribute `{}` is currently unknown to the \ - compiler and may have meaning added to it in the \ - future", path); - feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(), - GateIssue::Language, &msg).emit(); - } - } - return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool, - }))); - } - _ => { - self.report_non_macro_attr(path.span, def); - return Err(Determinacy::Determined); - } - } + let (def, ext) = self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?; + + if let Def::Macro(def_id, _) = def { + self.macro_defs.insert(invoc.expansion_data.mark, def_id); + let normal_module_def_id = + self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; + self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, + normal_module_def_id); + invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); + invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE); } - let def_id = def.def_id(); - - self.macro_defs.insert(invoc.expansion_data.mark, def_id); - let normal_module_def_id = - self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; - self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, - normal_module_def_id); - - self.unused_macros.remove(&def_id); - let ext = self.get_macro(def); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); - invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE); + Ok(Some(ext)) } - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result, Determinacy> { - self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| { - if let Def::Macro(_, MacroKind::ProcMacroStub) = def { - self.report_proc_macro_stub(path.span); - return Err(Determinacy::Determined); - } else if let Def::NonMacroAttr(..) = def { - self.report_non_macro_attr(path.span, def); - return Err(Determinacy::Determined); - } - self.unused_macros.remove(&def.def_id()); - Ok(self.get_macro(def)) - }) + fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark, + derives_in_scope: &[ast::Path], force: bool) + -> Result, Determinacy> { + Ok(self.resolve_macro_to_def(path, kind, scope, derives_in_scope, force)?.1) } fn check_unused_macros(&self) { @@ -428,95 +350,91 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { } impl<'a, 'cl> Resolver<'a, 'cl> { - fn report_proc_macro_stub(&self, span: Span) { - self.session.span_err(span, - "can't use a procedural macro from the same crate that defines it"); - } + fn resolve_macro_to_def(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark, + derives_in_scope: &[ast::Path], force: bool) + -> Result<(Def, Lrc), Determinacy> { + let def = self.resolve_macro_to_def_inner(path, kind, scope, derives_in_scope, force); - fn report_non_macro_attr(&self, span: Span, def: Def) { - self.session.span_err(span, &format!("expected a macro, found {}", def.kind_name())); - } - - fn resolve_invoc_to_def(&mut self, invoc: &Invocation, scope: Mark, force: bool) - -> Result { - let (attr, traits) = match invoc.kind { - InvocationKind::Attr { ref attr, ref traits, .. } => (attr, traits), - InvocationKind::Bang { ref mac, .. } => { - return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force); - } - InvocationKind::Derive { ref path, .. } => { - return self.resolve_macro_to_def(scope, path, MacroKind::Derive, force); + // Report errors and enforce feature gates for the resolved macro. + if def != Err(Determinacy::Undetermined) { + // Do not report duplicated errors on every undetermined resolution. + for segment in &path.segments { + if let Some(args) = &segment.args { + self.session.span_err(args.span(), "generic arguments in macro path"); + } } - }; - - let path = attr.as_ref().unwrap().path.clone(); - let def = self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force); - if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = def {} else { - return def; } - // At this point we've found that the `attr` is determinately unresolved and thus can be - // interpreted as a custom attribute. Normally custom attributes are feature gated, but - // it may be a custom attribute whitelisted by a derive macro and they do not require - // a feature gate. - // - // So here we look through all of the derive annotations in scope and try to resolve them. - // If they themselves successfully resolve *and* one of the resolved derive macros - // whitelists this attribute's name, then this is a registered attribute and we can convert - // it from a "generic custom attrite" into a "known derive helper attribute". - enum ConvertToDeriveHelper { Yes, No, DontKnow } - let mut convert_to_derive_helper = ConvertToDeriveHelper::No; - let attr_name = path.segments[0].ident.name; - for path in traits { - match self.resolve_macro(scope, path, MacroKind::Derive, force) { - Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext { - if inert_attrs.contains(&attr_name) { - convert_to_derive_helper = ConvertToDeriveHelper::Yes; - break - } - }, - Err(Determinacy::Undetermined) => - convert_to_derive_helper = ConvertToDeriveHelper::DontKnow, - Err(Determinacy::Determined) => {} - } - } + let def = def?; - match convert_to_derive_helper { - ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)), - ConvertToDeriveHelper::No => def, - ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)), + if path.segments.len() > 1 { + if kind != MacroKind::Bang { + if def != Def::NonMacroAttr(NonMacroAttrKind::Tool) && + !self.session.features_untracked().proc_macro_path_invoc { + let msg = format!("non-ident {} paths are unstable", kind.descr()); + emit_feature_err(&self.session.parse_sess, "proc_macro_path_invoc", + path.span, GateIssue::Language, &msg); + } + } } - } - fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result { - let def = self.resolve_macro_to_def_inner(scope, path, kind, force); - if def != Err(Determinacy::Undetermined) { - // Do not report duplicated errors on every undetermined resolution. - path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { - self.session.span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in macro path"); - }); - } - if kind != MacroKind::Bang && path.segments.len() > 1 && - def != Ok(Def::NonMacroAttr(NonMacroAttrKind::Tool)) { - if !self.session.features_untracked().proc_macro_path_invoc { - emit_feature_err( - &self.session.parse_sess, - "proc_macro_path_invoc", - path.span, - GateIssue::Language, - "paths of length greater than one in macro invocations are \ - currently unstable", - ); + match def { + Def::Macro(def_id, macro_kind) => { + self.unused_macros.remove(&def_id); + if macro_kind == MacroKind::ProcMacroStub { + let msg = "can't use a procedural macro from the same crate that defines it"; + self.session.span_err(path.span, msg); + return Err(Determinacy::Determined); + } + } + Def::NonMacroAttr(attr_kind) => { + if kind == MacroKind::Attr { + let features = self.session.features_untracked(); + if attr_kind == NonMacroAttrKind::Tool && !features.tool_attributes { + feature_err(&self.session.parse_sess, "tool_attributes", path.span, + GateIssue::Language, "tool attributes are unstable").emit(); + } + if attr_kind == NonMacroAttrKind::Custom { + assert!(path.segments.len() == 1); + let name = path.segments[0].ident.name.as_str(); + if name.starts_with("rustc_") { + if !features.rustc_attrs { + let msg = "unless otherwise specified, attributes with the prefix \ + `rustc_` are reserved for internal compiler diagnostics"; + feature_err(&self.session.parse_sess, "rustc_attrs", path.span, + GateIssue::Language, &msg).emit(); + } + } else if name.starts_with("derive_") { + if !features.custom_derive { + feature_err(&self.session.parse_sess, "custom_derive", path.span, + GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit(); + } + } else if !features.custom_attribute { + let msg = format!("The attribute `{}` is currently unknown to the \ + compiler and may have meaning added to it in the \ + future", path); + feature_err(&self.session.parse_sess, "custom_attribute", path.span, + GateIssue::Language, &msg).emit(); + } + } + } else { + // Not only attributes, but anything in macro namespace can result in + // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report + // an error for those cases. + let msg = format!("expected a macro, found {}", def.kind_name()); + self.session.span_err(path.span, &msg); + return Err(Determinacy::Determined); + } } + _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"), } - def + + Ok((def, self.get_macro(def))) } - pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path, - kind: MacroKind, force: bool) - -> Result { + pub fn resolve_macro_to_def_inner(&mut self, path: &ast::Path, kind: MacroKind, scope: 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]; @@ -558,12 +476,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); - let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution { - Ok(Def::Macro(binding.def_id, MacroKind::Bang)) + 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, kind == MacroKind::Attr, span) { - Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), + Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()), Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), Err(Determinacy::Determined) => { self.found_unresolved_macro = true; @@ -575,21 +493,56 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() .push((scope, path[0], kind, result.ok())); - result + if let Ok(Def::NonMacroAttr(NonMacroAttrKind::Custom)) = result {} else { + return result; + } + + // At this point we've found that the `attr` is determinately unresolved and thus can be + // interpreted as a custom attribute. Normally custom attributes are feature gated, but + // it may be a custom attribute whitelisted by a derive macro and they do not require + // a feature gate. + // + // So here we look through all of the derive annotations in scope and try to resolve them. + // If they themselves successfully resolve *and* one of the resolved derive macros + // whitelists this attribute's name, then this is a registered attribute and we can convert + // it from a "generic custom attrite" into a "known derive helper attribute". + assert!(kind == MacroKind::Attr); + 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) { + Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext { + if inert_attrs.contains(&path[0].name) { + convert_to_derive_helper = ConvertToDeriveHelper::Yes; + break + } + }, + Err(Determinacy::Undetermined) => + convert_to_derive_helper = ConvertToDeriveHelper::DontKnow, + Err(Determinacy::Determined) => {} + } + } + + match convert_to_derive_helper { + ConvertToDeriveHelper::Yes => Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)), + ConvertToDeriveHelper::No => result, + ConvertToDeriveHelper::DontKnow => Err(Determinacy::determined(force)), + } } // Resolve the initial segment of a non-global macro path // (e.g. `foo` in `foo::bar!(); or `foo!();`). // 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). - pub fn resolve_lexical_macro_path_segment(&mut self, - mut ident: Ident, - ns: Namespace, - record_used: bool, - force: bool, - is_attr: bool, - path_span: Span) - -> Result, Determinacy> { + crate fn resolve_lexical_macro_path_segment( + &mut self, + mut ident: Ident, + ns: Namespace, + record_used: bool, + force: bool, + is_attr: bool, + path_span: Span + ) -> Result<(&'a NameBinding<'a>, FromPrelude), 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 @@ -629,7 +582,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // m::mac!(); // } // This includes names from globs and from macro expansions. - let mut potentially_ambiguous_result: Option = None; + let mut potentially_ambiguous_result: Option<(&NameBinding, FromPrelude)> = None; enum WhereToResolve<'a> { Module(Module<'a>), @@ -657,11 +610,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { path_span, ); self.current_module = orig_current_module; - binding.map(MacroBinding::Modern) + binding.map(|binding| (binding, FromPrelude(false))) } WhereToResolve::MacroPrelude => { match self.macro_prelude.get(&ident.name).cloned() { - Some(binding) => Ok(MacroBinding::Global(binding)), + Some(binding) => Ok((binding, FromPrelude(true))), None => Err(Determinacy::Determined), } } @@ -673,7 +626,7 @@ 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(MacroBinding::Global(binding)) + Ok((binding, FromPrelude(true))) } else { Err(Determinacy::Determined) } @@ -696,7 +649,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); - Ok(MacroBinding::Global(binding)) + Ok((binding, FromPrelude(true))) } else { Err(Determinacy::Determined) } @@ -705,7 +658,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(MacroBinding::Global(binding)) + Ok((binding, FromPrelude(true))) } else { Err(Determinacy::Determined) } @@ -722,7 +675,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { false, path_span, ) { - result = Ok(MacroBinding::Global(binding)); + result = Ok((binding, FromPrelude(true))); } } } @@ -733,7 +686,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { 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(MacroBinding::Global(binding)) + Ok((binding, FromPrelude(true))) } else { Err(Determinacy::Determined) } @@ -772,18 +725,16 @@ impl<'a, 'cl> Resolver<'a, 'cl> { return Ok(result); } - let binding = result.binding(); - // 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 binding.def() != previous_result.binding().def() { + if result.0.def() != previous_result.0.def() { self.ambiguity_errors.push(AmbiguityError { span: path_span, name: ident.name, - b1: previous_result.binding(), - b2: binding, + b1: previous_result.0, + b2: result.0, lexical: true, }); return Ok(previous_result); @@ -793,7 +744,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 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 binding.is_glob_import() || binding.expansion != Mark::root() { + if result.0.is_glob_import() || result.0.expansion != Mark::root() { potentially_ambiguous_result = Some(result); continue_search!(); @@ -823,20 +774,19 @@ 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(MacroBinding::Global(binding)) + Ok((binding, FromPrelude(true))) } else { Err(determinacy) } } - pub fn resolve_legacy_scope(&mut self, - mut scope: &'a Cell>, - ident: Ident, - record_used: bool) - -> Option> { + crate fn resolve_legacy_scope(&mut self, + mut scope: &'a Cell>, + ident: Ident, + record_used: bool) + -> Option<(&'a LegacyBinding<'a>, FromExpansion)> { let ident = ident.modern(); let mut relative_depth: u32 = 0; - let mut binding = None; loop { match scope.get() { LegacyScope::Empty => break, @@ -861,23 +811,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if record_used && relative_depth > 0 { self.disallowed_shadowing.push(potential_binding); } - binding = Some(potential_binding); - break + return Some((potential_binding, FromExpansion(relative_depth > 0))); } scope = &potential_binding.parent; } }; } - let binding = if let Some(binding) = binding { - MacroBinding::Legacy(binding) - } else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() { - MacroBinding::Global(binding) - } else { - return None; - }; - - Some(binding) + None } pub fn finalize_current_module_macro_resolutions(&mut self) { @@ -899,10 +840,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, true, kind == MacroKind::Attr, span); - let check_consistency = |this: &Self, binding: MacroBinding| { + let check_consistency = |this: &Self, new_def: Def| { if let Some(def) = def { if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() && - binding.def_ignoring_ambiguity() != def { + 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. @@ -921,17 +862,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }; match (legacy_resolution, resolution) { - (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => { - if legacy_binding.def_id != binding.def_ignoring_ambiguity().def_id() { - let msg1 = format!("`{}` could refer to the macro defined here", ident); - let msg2 = - format!("`{}` could also refer to the macro imported here", ident); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) - .span_note(legacy_binding.span, &msg1) - .span_note(binding.span, &msg2) - .emit(); - } - }, (None, Err(_)) => { assert!(def.is_none()); let bang = if kind == MacroKind::Bang { "!" } else { "" }; @@ -941,26 +871,34 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.suggest_macro_name(&ident.as_str(), kind, &mut err, span); err.emit(); }, - (Some(MacroBinding::Modern(_)), _) | (_, Ok(MacroBinding::Legacy(_))) => { - span_bug!(span, "impossible macro resolution result"); - } + (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, + ); + } + }, + // OK, non-macro-expanded legacy wins over macro prelude even if defs are different + (Some((legacy_binding, FromExpansion(false))), Ok((_, FromPrelude(true)))) | // OK, unambiguous resolution - (Some(binding), Err(_)) | (None, Ok(binding)) | - // OK, legacy wins over global even if their definitions are different - (Some(binding @ MacroBinding::Legacy(_)), Ok(MacroBinding::Global(_))) | - // OK, modern wins over global even if their definitions are different - (Some(MacroBinding::Global(_)), Ok(binding @ MacroBinding::Modern(_))) => { - check_consistency(self, binding); + (Some((legacy_binding, _)), Err(_)) => { + check_consistency(self, legacy_binding.def()); } - (Some(MacroBinding::Global(binding1)), Ok(MacroBinding::Global(binding2))) => { - if binding1.def() != binding2.def() { - span_bug!(span, "mismatch between same global macro resolutions"); + // 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.err_if_macro_use_proc_macro(ident.name, span, binding); } - check_consistency(self, MacroBinding::Global(binding1)); - - self.record_use(ident, MacroNS, binding1, span); - self.err_if_macro_use_proc_macro(ident.name, span, binding1); - }, + } }; } } @@ -1082,7 +1020,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]` fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span, binding: &NameBinding<'a>) { - let krate = binding.def().def_id().krate; + let krate = match binding.def() { + Def::NonMacroAttr(..) | Def::Err => return, + Def::Macro(def_id, _) => def_id.krate, + _ => unreachable!(), + }; // Plugin-based syntax extensions are exempt from this check if krate == BUILTIN_MACROS_CRATE { return; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 28d504c2ee0c8..c00d67aaab6b4 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -403,9 +403,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { let path = ast::Path { segments: vec![segment], span: DUMMY_SP }; let mut resolver = cx.resolver.borrow_mut(); let mark = Mark::root(); - let res = resolver - .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false); - if let Ok(def) = res { + if let Ok(def) = resolver.resolve_macro_to_def_inner(&path, MacroKind::Bang, mark, &[], false) { if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) { return Some(def); } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 154fe11dd352c..c9925b41498cf 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -727,10 +727,12 @@ pub trait Resolver { fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) -> Option; - fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool) - -> Result>, Determinacy>; - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result, Determinacy>; + fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool) + -> Result>, Determinacy>; + fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark, + derives_in_scope: &[ast::Path], force: bool) + -> Result, Determinacy>; + fn check_unused_macros(&self); } @@ -761,12 +763,13 @@ impl Resolver for DummyResolver { fn resolve_imports(&mut self) {} fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec, _allow_derive: bool) -> Option { None } - fn resolve_invoc(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool) - -> Result>, Determinacy> { + fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool) + -> Result>, Determinacy> { Err(Determinacy::Determined) } - fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind, - _force: bool) -> Result, Determinacy> { + fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _scope: Mark, + _derives_in_scope: &[ast::Path], _force: bool) + -> Result, Determinacy> { Err(Determinacy::Determined) } fn check_unused_macros(&self) {} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 06e4087171a83..97279e00869c6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -243,15 +243,6 @@ impl Invocation { InvocationKind::Derive { ref path, .. } => path.span, } } - - pub fn path(&self) -> Option<&Path> { - match self.kind { - InvocationKind::Bang { ref mac, .. } => Some(&mac.node.path), - InvocationKind::Attr { attr: Some(ref attr), .. } => Some(&attr.path), - InvocationKind::Attr { attr: None, .. } => None, - InvocationKind::Derive { ref path, .. } => Some(path), - } - } } pub struct MacroExpander<'a, 'b:'a> { @@ -343,7 +334,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let scope = if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; - let ext = match self.cx.resolver.resolve_invoc(&invoc, scope, force) { + let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) { Ok(ext) => Some(ext), Err(Determinacy::Determined) => None, Err(Determinacy::Undetermined) => { @@ -393,8 +384,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { for path in &traits { let mark = Mark::fresh(self.cx.current_expansion.mark); derives.push(mark); - let item = match self.cx.resolver.resolve_macro( - Mark::root(), path, MacroKind::Derive, false) { + let item = match self.cx.resolver.resolve_macro_path( + path, MacroKind::Derive, Mark::root(), &[], false) { Ok(ext) => match *ext { BuiltinDerive(..) => item_with_markers.clone(), _ => item.clone(), diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs index 0798aa549f0b2..96f68341db7a7 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs @@ -22,7 +22,7 @@ extern crate proc_macro_gates as foo; use foo::*; -#[foo::a] //~ ERROR: paths of length greater than one +#[foo::a] //~ ERROR: non-ident attribute macro paths are unstable fn _test() {} fn _test_inner() { diff --git a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr index 342d7ddb36cf2..9def03e94506a 100644 --- a/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr +++ b/src/test/ui-fulldeps/proc-macro/macro-namespace-reserved-2.stderr @@ -2,37 +2,37 @@ error: can't use a procedural macro from the same crate that defines it --> $DIR/macro-namespace-reserved-2.rs:34:5 | LL | my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^^^ + | ^^^^^^^^ error: can't use a procedural macro from the same crate that defines it --> $DIR/macro-namespace-reserved-2.rs:37:5 | LL | my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: can't use a procedural macro from the same crate that defines it --> $DIR/macro-namespace-reserved-2.rs:40:5 | LL | MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^^ + | ^^^^^^^ error: can't use a procedural macro from the same crate that defines it - --> $DIR/macro-namespace-reserved-2.rs:43:1 + --> $DIR/macro-namespace-reserved-2.rs:43:3 | LL | #[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^^ + | ^^^^^^^^ error: can't use a procedural macro from the same crate that defines it - --> $DIR/macro-namespace-reserved-2.rs:45:1 + --> $DIR/macro-namespace-reserved-2.rs:45:3 | LL | #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: can't use a procedural macro from the same crate that defines it - --> $DIR/macro-namespace-reserved-2.rs:47:1 + --> $DIR/macro-namespace-reserved-2.rs:47:3 | LL | #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it - | ^^^^^^^^^^ + | ^^^^^^^ error: can't use a procedural macro from the same crate that defines it --> $DIR/macro-namespace-reserved-2.rs:50:10 diff --git a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr index 33fe52366dbbb..0f51c7d68c642 100644 --- a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr +++ b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -2,7 +2,7 @@ error[E0658]: The attribute `unknown` is currently unknown to the compiler and m --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27 | LL | #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown - | ^^^^^^^^ + | ^^^^^^^ ... LL | foo!(); | ------- in this macro invocation diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr index 4adfe1e450ee5..6ecad7d79b867 100644 --- a/src/test/ui/custom_attribute.stderr +++ b/src/test/ui/custom_attribute.stderr @@ -1,24 +1,24 @@ error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/custom_attribute.rs:13:1 + --> $DIR/custom_attribute.rs:13:3 | LL | #[foo] //~ ERROR The attribute `foo` - | ^^^^^^ + | ^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/custom_attribute.rs:15:5 + --> $DIR/custom_attribute.rs:15:7 | LL | #[foo] //~ ERROR The attribute `foo` - | ^^^^^^ + | ^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/custom_attribute.rs:17:5 + --> $DIR/custom_attribute.rs:17:7 | LL | #[foo] //~ ERROR The attribute `foo` - | ^^^^^^ + | ^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr index 36f5898f1c70e..e60e9a342a99c 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr @@ -1,104 +1,104 @@ error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:17:1 + --> $DIR/feature-gate-custom_attribute.rs:17:3 | LL | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:18:1 + --> $DIR/feature-gate-custom_attribute.rs:18:3 | LL | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:19:1 + --> $DIR/feature-gate-custom_attribute.rs:19:3 | LL | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:20:1 + --> $DIR/feature-gate-custom_attribute.rs:20:3 | LL | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:21:1 + --> $DIR/feature-gate-custom_attribute.rs:21:3 | LL | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:22:1 + --> $DIR/feature-gate-custom_attribute.rs:22:3 | LL | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:23:1 + --> $DIR/feature-gate-custom_attribute.rs:23:3 | LL | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:24:1 + --> $DIR/feature-gate-custom_attribute.rs:24:3 | LL | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:25:1 + --> $DIR/feature-gate-custom_attribute.rs:25:3 | LL | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:26:1 + --> $DIR/feature-gate-custom_attribute.rs:26:3 | LL | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:27:1 + --> $DIR/feature-gate-custom_attribute.rs:27:3 | LL | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:28:1 + --> $DIR/feature-gate-custom_attribute.rs:28:3 | LL | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute.rs:29:1 + --> $DIR/feature-gate-custom_attribute.rs:29:3 | LL | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr b/src/test/ui/feature-gates/feature-gate-custom_derive.stderr index e633a5a9c9930..0979372daea30 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr +++ b/src/test/ui/feature-gates/feature-gate-custom_derive.stderr @@ -1,8 +1,8 @@ error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) - --> $DIR/feature-gate-custom_derive.rs:11:1 + --> $DIR/feature-gate-custom_derive.rs:11:3 | LL | #[derive_Clone] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add #![feature(custom_derive)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 52a4d3664ce23..882549c1eafba 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -1,8 +1,8 @@ error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) - --> $DIR/feature-gate-rustc-attrs.rs:15:1 + --> $DIR/feature-gate-rustc-attrs.rs:15:3 | LL | #[rustc_foo] - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(rustc_attrs)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr index ca9542dcc956a..b024059d45014 100644 --- a/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr +++ b/src/test/ui/feature-gates/feature-gate-tool_attributes.stderr @@ -1,8 +1,8 @@ error[E0658]: tool attributes are unstable (see issue #44690) - --> $DIR/feature-gate-tool_attributes.rs:12:5 + --> $DIR/feature-gate-tool_attributes.rs:12:7 | LL | #[rustfmt::skip] //~ ERROR tool attributes are unstable - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = help: add #![feature(tool_attributes)] to the crate attributes to enable diff --git a/src/test/ui/imports/issue-53269.rs b/src/test/ui/imports/issue-53269.rs new file mode 100644 index 0000000000000..1b21e3ba5f3a7 --- /dev/null +++ b/src/test/ui/imports/issue-53269.rs @@ -0,0 +1,21 @@ +// Copyright 2018 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. + +// Ambiguity between a `macro_rules` macro and a non-existent import recovered as `Def::Err` + +macro_rules! mac { () => () } + +mod m { + use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module` + + mac!(); //~ ERROR `mac` is ambiguous +} + +fn main() {} diff --git a/src/test/ui/imports/issue-53269.stderr b/src/test/ui/imports/issue-53269.stderr new file mode 100644 index 0000000000000..0036d71107a95 --- /dev/null +++ b/src/test/ui/imports/issue-53269.stderr @@ -0,0 +1,27 @@ +error[E0432]: unresolved import `nonexistent_module` + --> $DIR/issue-53269.rs:16:9 + | +LL | use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module` + | ^^^^^^^^^^^^^^^^^^ Maybe a missing `extern crate nonexistent_module;`? + +error[E0659]: `mac` is ambiguous + --> $DIR/issue-53269.rs:18:5 + | +LL | mac!(); //~ ERROR `mac` is ambiguous + | ^^^ + | +note: `mac` could refer to the name defined here + --> $DIR/issue-53269.rs:13:1 + | +LL | macro_rules! mac { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `mac` could also refer to the name imported here + --> $DIR/issue-53269.rs:16:9 + | +LL | use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module` + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors occurred: E0432, E0659. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/issue-53512.rs b/src/test/ui/imports/issue-53512.rs new file mode 100644 index 0000000000000..82ae75e8198ac --- /dev/null +++ b/src/test/ui/imports/issue-53512.rs @@ -0,0 +1,17 @@ +// Copyright 2018 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. + +// Macro from prelude is shadowed by non-existent import recovered as `Def::Err`. + +use std::assert; //~ ERROR unresolved import `std::assert` + +fn main() { + assert!(true); +} diff --git a/src/test/ui/imports/issue-53512.stderr b/src/test/ui/imports/issue-53512.stderr new file mode 100644 index 0000000000000..e79e759f6c69f --- /dev/null +++ b/src/test/ui/imports/issue-53512.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `std::assert` + --> $DIR/issue-53512.rs:13:5 + | +LL | use std::assert; //~ ERROR unresolved import `std::assert` + | ^^^^^^^^^^^ no `assert` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index 01d1f4fdfad03..2c0c4642067ac 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -1,15 +1,15 @@ -error: `m` is ambiguous +error[E0659]: `m` is ambiguous --> $DIR/macros.rs:48:5 | LL | m!(); //~ ERROR ambiguous | ^ | -note: `m` could refer to the macro defined here +note: `m` could refer to the name defined here --> $DIR/macros.rs:46:5 | LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: `m` could also refer to the macro imported here +note: `m` could also refer to the name imported here --> $DIR/macros.rs:47:9 | LL | use two_macros::m; diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs index 90718abc37b31..ec3f4107e38fc 100644 --- a/src/test/ui/imports/shadow_builtin_macros.rs +++ b/src/test/ui/imports/shadow_builtin_macros.rs @@ -37,10 +37,10 @@ mod m4 { mod m5 { macro_rules! m { () => { - macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope + macro_rules! panic { () => {} } } } m!(); - panic!(); + panic!(); //~ ERROR `panic` is ambiguous } #[macro_use(n)] diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 693b7aadeca4e..5c7f15b6fe26f 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -1,13 +1,19 @@ -error: `panic` is already in scope +error[E0659]: `panic` is ambiguous + --> $DIR/shadow_builtin_macros.rs:43:5 + | +LL | panic!(); //~ ERROR `panic` is ambiguous + | ^^^^^ + | +note: `panic` could refer to the name defined here --> $DIR/shadow_builtin_macros.rs:40:9 | -LL | macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope +LL | macro_rules! panic { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | } } LL | m!(); | ----- in this macro invocation - | - = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560) + = 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 diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index a1323808a91ea..f930217fe9ef5 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -1,8 +1,8 @@ error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) - --> $DIR/issue-32655.rs:16:9 + --> $DIR/issue-32655.rs:16:11 | LL | #[derive_Clone] //~ ERROR attributes of the form - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ... LL | foo!(); | ------- in this macro invocation @@ -10,10 +10,10 @@ LL | foo!(); = help: add #![feature(custom_derive)] to the crate attributes to enable error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) - --> $DIR/issue-32655.rs:28:5 + --> $DIR/issue-32655.rs:28:7 | LL | #[derive_Clone] //~ ERROR attributes of the form - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | = help: add #![feature(custom_derive)] to the crate attributes to enable diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr index 888222b69cc4e..6c9d1eac35684 100644 --- a/src/test/ui/issues/issue-49074.stderr +++ b/src/test/ui/issues/issue-49074.stderr @@ -1,8 +1,8 @@ error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/issue-49074.rs:13:1 + --> $DIR/issue-49074.rs:13:3 | LL | #[marco_use] // typo - | ^^^^^^^^^^^^ + | ^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr index c93c7144f9ebe..8f954158a6315 100644 --- a/src/test/ui/macros/macro-reexport-removed.stderr +++ b/src/test/ui/macros/macro-reexport-removed.stderr @@ -11,10 +11,10 @@ LL | #![feature(macro_reexport)] //~ ERROR feature has been removed | ^^^^^^^^^^^^^^ error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/macro-reexport-removed.rs:15:1 + --> $DIR/macro-reexport-removed.rs:15:3 | LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index e8bfcc04f48b9..efcd1ec67d7e9 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -1,8 +1,8 @@ error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) - --> $DIR/reserved-attr-on-macro.rs:11:1 + --> $DIR/reserved-attr-on-macro.rs:11:3 | LL | #[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(rustc_attrs)] to the crate attributes to enable diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index cbec4f6b0a63b..e7dd8e7aa8fa0 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -1,16 +1,16 @@ error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/issue-36530.rs:11:1 + --> $DIR/issue-36530.rs:11:3 | LL | #[foo] //~ ERROR is currently unknown to the compiler - | ^^^^^^ + | ^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/issue-36530.rs:13:5 + --> $DIR/issue-36530.rs:13:8 | LL | #![foo] //~ ERROR is currently unknown to the compiler - | ^^^^^^^ + | ^^^ | = help: add #![feature(custom_attribute)] to the crate attributes to enable