diff options
Diffstat (limited to 'compiler/rustc_resolve/src/macros.rs')
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 134 |
1 files changed, 71 insertions, 63 deletions
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index e052b6b3345..c8dbe685128 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -12,24 +12,24 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; +use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension}; use rustc_expand::compile_declarative_macro; -use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; +use rustc_expand::expand::{AstFragment, Invocation, InvocationKind}; use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id; use rustc_middle::middle::stability; use rustc_middle::ty; -use rustc_session::lint::builtin::UNUSED_MACROS; +use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS}; +use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind}; +use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; - -use rustc_data_structures::sync::Lrc; -use rustc_span::hygiene::{AstPass, MacroKind}; use std::cell::Cell; use std::{mem, ptr}; @@ -241,15 +241,20 @@ impl<'a> ResolverExpand for Resolver<'a> { } }; - let (path, kind, derives, after_derive) = match invoc.kind { + let (path, kind, inner_attr, derives, after_derive) = match invoc.kind { InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => ( &attr.get_normal_item().path, MacroKind::Attr, + attr.style == ast::AttrStyle::Inner, self.arenas.alloc_ast_paths(derives), after_derive, ), - InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang, &[][..], false), - InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, &[][..], false), + InvocationKind::Bang { ref mac, .. } => { + (&mac.path, MacroKind::Bang, false, &[][..], false) + } + InvocationKind::Derive { ref path, .. } => { + (path, MacroKind::Derive, false, &[][..], false) + } InvocationKind::DeriveContainer { ref derives, .. } => { // Block expansion of the container until we resolve all derives in it. // This is required for two reasons: @@ -281,7 +286,7 @@ impl<'a> ResolverExpand for Resolver<'a> { ext.helper_attrs.iter().map(|name| Ident::new(*name, span)), ); if ext.is_derive_copy { - self.add_derive_copy(invoc_id); + self.containers_deriving_copy.insert(invoc_id); } ext } @@ -299,8 +304,17 @@ impl<'a> ResolverExpand for Resolver<'a> { // Derives are not included when `invocations` are collected, so we have to add them here. let parent_scope = &ParentScope { derives, ..parent_scope }; + let require_inert = !invoc.fragment_kind.supports_macro_expansion(); let node_id = self.lint_node_id(eager_expansion_root); - let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, node_id, force)?; + let (ext, res) = self.smart_resolve_macro_path( + path, + kind, + require_inert, + inner_attr, + parent_scope, + node_id, + force, + )?; let span = invoc.span(); invoc_id.set_expn_data(ext.expn_data( @@ -318,29 +332,6 @@ impl<'a> ResolverExpand for Resolver<'a> { self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); } - match invoc.fragment_kind { - AstFragmentKind::Arms - | AstFragmentKind::Fields - | AstFragmentKind::FieldPats - | AstFragmentKind::GenericParams - | AstFragmentKind::Params - | AstFragmentKind::StructFields - | AstFragmentKind::Variants => { - if let Res::Def(..) = res { - self.session.span_err( - span, - &format!( - "expected an inert attribute, found {} {}", - res.article(), - res.descr() - ), - ); - return Ok(InvocationRes::Single(self.dummy_ext(kind))); - } - } - _ => {} - } - Ok(InvocationRes::Single(ext)) } @@ -360,10 +351,6 @@ impl<'a> ResolverExpand for Resolver<'a> { self.containers_deriving_copy.contains(&expn_id) } - fn add_derive_copy(&mut self, expn_id: ExpnId) { - self.containers_deriving_copy.insert(expn_id); - } - // The function that implements the resolution logic of `#[cfg_accessible(path)]`. // Returns true if the path can certainly be resolved in one of three namespaces, // returns false if the path certainly cannot be resolved in any of the three namespaces. @@ -403,10 +390,14 @@ impl<'a> ResolverExpand for Resolver<'a> { impl<'a> Resolver<'a> { /// Resolve macro path with error reporting and recovery. + /// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions + /// for better error recovery. fn smart_resolve_macro_path( &mut self, path: &ast::Path, kind: MacroKind, + require_inert: bool, + inner_attr: bool, parent_scope: &ParentScope<'a>, node_id: NodeId, force: bool, @@ -414,7 +405,6 @@ impl<'a> Resolver<'a> { let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force) { Ok((Some(ext), res)) => (ext, res), - // Use dummy syntax extensions for unresolved macros for better recovery. Ok((None, res)) => (self.dummy_ext(kind), res), Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err), Err(Determinacy::Undetermined) => return Err(Indeterminate), @@ -451,19 +441,42 @@ impl<'a> Resolver<'a> { self.check_stability_and_deprecation(&ext, path, node_id); - Ok(if ext.macro_kind() != kind { - let expected = kind.descr_expected(); + let unexpected_res = if ext.macro_kind() != kind { + Some((kind.article(), kind.descr_expected())) + } else if require_inert && matches!(res, Res::Def(..)) { + Some(("a", "non-macro attribute")) + } else { + None + }; + if let Some((article, expected)) = unexpected_res { let path_str = pprust::path_to_string(path); let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str); self.session .struct_span_err(path.span, &msg) - .span_label(path.span, format!("not {} {}", kind.article(), expected)) + .span_label(path.span, format!("not {} {}", article, expected)) .emit(); - // Use dummy syntax extensions for unexpected macro kinds for better recovery. - (self.dummy_ext(kind), Res::Err) - } else { - (ext, res) - }) + return Ok((self.dummy_ext(kind), Res::Err)); + } + + // We are trying to avoid reporting this error if other related errors were reported. + if res != Res::Err + && inner_attr + && !self.session.features_untracked().custom_inner_attributes + { + let msg = match res { + Res::Def(..) => "inner macro attributes are unstable", + Res::NonMacroAttr(..) => "custom inner attributes are unstable", + _ => unreachable!(), + }; + if path == &sym::test { + self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); + } else { + feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg) + .emit(); + } + } + + Ok((ext, res)) } pub fn resolve_macro_path( @@ -568,10 +581,9 @@ impl<'a> Resolver<'a> { struct Flags: u8 { const MACRO_RULES = 1 << 0; const MODULE = 1 << 1; - const DERIVE_HELPER_COMPAT = 1 << 2; - const MISC_SUGGEST_CRATE = 1 << 3; - const MISC_SUGGEST_SELF = 1 << 4; - const MISC_FROM_PRELUDE = 1 << 5; + const MISC_SUGGEST_CRATE = 1 << 2; + const MISC_SUGGEST_SELF = 1 << 3; + const MISC_FROM_PRELUDE = 1 << 4; } } @@ -646,14 +658,11 @@ impl<'a> Resolver<'a> { ) { Ok((Some(ext), _)) => { if ext.helper_attrs.contains(&ident.name) { - let binding = ( - Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - ty::Visibility::Public, + result = ok( + Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat), derive.span, - ExpnId::root(), - ) - .to_name_binding(this.arenas); - result = Ok((binding, Flags::DERIVE_HELPER_COMPAT)); + this.arenas, + ); break; } } @@ -799,17 +808,15 @@ impl<'a> Resolver<'a> { let (res, innermost_res) = (binding.res(), innermost_binding.res()); if res != innermost_res { let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin); - let is_derive_helper_compat = |res, flags: Flags| { - res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper) - && flags.contains(Flags::DERIVE_HELPER_COMPAT) - }; + let derive_helper_compat = + Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat); let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) } else if innermost_res == builtin || res == builtin { Some(AmbiguityKind::BuiltinAttr) - } else if is_derive_helper_compat(innermost_res, innermost_flags) - || is_derive_helper_compat(res, flags) + } else if innermost_res == derive_helper_compat + || res == derive_helper_compat { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) @@ -1034,6 +1041,7 @@ impl<'a> Resolver<'a> { depr.suggestion, lint, span, + node_id, ); } } |
