summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/macros.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/macros.rs')
-rw-r--r--compiler/rustc_resolve/src/macros.rs52
1 files changed, 37 insertions, 15 deletions
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index b38c11e8b..22b014c06 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,14 +1,14 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.
+use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
use crate::Namespace::*;
use crate::{BuiltinMacroState, Determinacy};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment};
-use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId};
+use rustc_ast::{self as ast, attr, Inline, ItemKind, ModKind, NodeId};
use rustc_ast_pretty::pprust;
use rustc_attr::StabilityLevel;
-use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{struct_span_err, Applicability};
@@ -20,11 +20,11 @@ use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
use rustc_hir::def_id::{CrateNum, LocalDefId};
use rustc_middle::middle::stability;
use rustc_middle::ty::RegisteredTools;
+use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::feature_err;
-use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::hygiene::{AstPass, MacroKind};
@@ -111,15 +111,17 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
}
}
-pub(crate) fn registered_tools(sess: &Session, attrs: &[ast::Attribute]) -> FxHashSet<Ident> {
- let mut registered_tools = FxHashSet::default();
- for attr in sess.filter_by_name(attrs, sym::register_tool) {
+pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
+ let mut registered_tools = RegisteredTools::default();
+ let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
+ for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) {
for nested_meta in attr.meta_item_list().unwrap_or_default() {
match nested_meta.ident() {
Some(ident) => {
if let Some(old_ident) = registered_tools.replace(ident) {
let msg = format!("{} `{}` was already registered", "tool", ident);
- sess.struct_span_err(ident.span, &msg)
+ tcx.sess
+ .struct_span_err(ident.span, &msg)
.span_label(old_ident.span, "already registered here")
.emit();
}
@@ -127,7 +129,10 @@ pub(crate) fn registered_tools(sess: &Session, attrs: &[ast::Attribute]) -> FxHa
None => {
let msg = format!("`{}` only accepts identifiers", sym::register_tool);
let span = nested_meta.span();
- sess.struct_span_err(span, &msg).span_label(span, "not an identifier").emit();
+ tcx.sess
+ .struct_span_err(span, &msg)
+ .span_label(span, "not an identifier")
+ .emit();
}
}
}
@@ -539,12 +544,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
};
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.tcx
- .sess
- .struct_span_err(path.span, &msg)
- .span_label(path.span, format!("not {} {}", article, expected))
- .emit();
+
+ let mut err = MacroExpectedFound {
+ span: path.span,
+ expected,
+ found: res.descr(),
+ macro_path: &path_str,
+ ..Default::default() // Subdiagnostics default to None
+ };
+
+ // Suggest moving the macro out of the derive() if the macro isn't Derive
+ if !path.span.from_expansion()
+ && kind == MacroKind::Derive
+ && ext.macro_kind() != MacroKind::Derive
+ {
+ err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
+ err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
+ }
+
+ let mut err = self.tcx.sess.create_err(err);
+ err.span_label(path.span, format!("not {} {}", article, expected));
+
+ err.emit();
+
return Ok((self.dummy_ext(kind), Res::Err));
}
@@ -699,7 +721,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
check_consistency(self, &path, path_span, kind, initial_res, res)
}
- path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => {
+ path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => {
let mut suggestion = None;
let (span, label) = if let PathResult::Failed { span, label, .. } = path_res {
// try to suggest if it's not a macro, maybe a function