mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
Rollup merge of #39953 - keeperofdakeys:macro-error, r=jseyfried
Provide suggestions for unknown macros imported with `use` cc https://github.com/rust-lang/rust/issues/30197 r? @jseyfried
This commit is contained in:
commit
a6a5c32e0e
@ -11,6 +11,7 @@
|
||||
use hir::def_id::DefId;
|
||||
use util::nodemap::NodeMap;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use hir;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
@ -53,7 +54,7 @@ pub enum Def {
|
||||
Label(ast::NodeId),
|
||||
|
||||
// Macro namespace
|
||||
Macro(DefId),
|
||||
Macro(DefId, MacroKind),
|
||||
|
||||
// Both namespaces
|
||||
Err,
|
||||
@ -141,7 +142,7 @@ impl Def {
|
||||
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
|
||||
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
|
||||
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
|
||||
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => {
|
||||
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
|
||||
id
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
||||
use syntax::attr;
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
||||
|
||||
pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
@ -434,7 +435,7 @@ impl<'tcx> EntryKind<'tcx> {
|
||||
EntryKind::Variant(_) => Def::Variant(did),
|
||||
EntryKind::Trait(_) => Def::Trait(did),
|
||||
EntryKind::Enum(..) => Def::Enum(did),
|
||||
EntryKind::MacroDef(_) => Def::Macro(did),
|
||||
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
|
||||
|
||||
EntryKind::ForeignMod |
|
||||
EntryKind::Impl(_) |
|
||||
@ -483,9 +484,11 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
|
||||
pub fn get_def(&self, index: DefIndex) -> Option<Def> {
|
||||
match self.is_proc_macro(index) {
|
||||
true => Some(Def::Macro(self.local_def_id(index))),
|
||||
false => self.entry(index).kind.to_def(self.local_def_id(index)),
|
||||
if !self.is_proc_macro(index) {
|
||||
self.entry(index).kind.to_def(self.local_def_id(index))
|
||||
} else {
|
||||
let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
|
||||
Some(Def::Macro(self.local_def_id(index), kind))
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,8 +691,14 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
{
|
||||
if let Some(ref proc_macros) = self.proc_macros {
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for (id, &(name, _)) in proc_macros.iter().enumerate() {
|
||||
let def = Def::Macro(DefId { krate: self.cnum, index: DefIndex::new(id + 1) });
|
||||
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
|
||||
let def = Def::Macro(
|
||||
DefId {
|
||||
krate: self.cnum,
|
||||
index: DefIndex::new(id + 1)
|
||||
},
|
||||
ext.kind()
|
||||
);
|
||||
callback(def::Export { name: name, def: def });
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
|
||||
let def_id = match def {
|
||||
Def::Macro(def_id) => def_id,
|
||||
Def::Macro(def_id, ..) => def_id,
|
||||
_ => panic!("Expected Def::Macro(..)"),
|
||||
};
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
@ -537,7 +537,6 @@ impl<'a> Resolver<'a> {
|
||||
binding: &'a NameBinding<'a>,
|
||||
span: Span,
|
||||
allow_shadowing: bool) {
|
||||
self.macro_names.insert(name);
|
||||
if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
|
||||
let msg = format!("`{}` is already in scope", name);
|
||||
let note =
|
||||
|
@ -1265,7 +1265,7 @@ impl<'a> Resolver<'a> {
|
||||
ribs: PerNS {
|
||||
value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
|
||||
type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
|
||||
macro_ns: None,
|
||||
macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]),
|
||||
},
|
||||
label_ribs: Vec::new(),
|
||||
|
||||
@ -2328,10 +2328,13 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
}
|
||||
}
|
||||
if primary_ns != MacroNS && path.len() == 1 &&
|
||||
self.macro_names.contains(&path[0].name) {
|
||||
let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
|
||||
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
|
||||
if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
|
||||
// Return some dummy definition, it's enough for error reporting.
|
||||
return Some(PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX))));
|
||||
return Some(
|
||||
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
|
||||
);
|
||||
}
|
||||
fin_res
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ 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::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
|
||||
use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::ext::expand::{Expansion, mark_tts};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
@ -152,16 +152,14 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
|
||||
if let NormalTT(..) = *ext {
|
||||
self.macro_names.insert(ident.name);
|
||||
}
|
||||
let def_id = DefId {
|
||||
krate: BUILTIN_MACROS_CRATE,
|
||||
index: DefIndex::new(self.macro_map.len()),
|
||||
};
|
||||
let kind = ext.kind();
|
||||
self.macro_map.insert(def_id, ext);
|
||||
let binding = self.arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Def(Def::Macro(def_id)),
|
||||
kind: NameBindingKind::Def(Def::Macro(def_id, kind)),
|
||||
span: DUMMY_SP,
|
||||
vis: ty::Visibility::Invisible,
|
||||
expansion: Mark::root(),
|
||||
@ -470,24 +468,40 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
|
||||
err: &mut DiagnosticBuilder<'a>) {
|
||||
let suggestion = match kind {
|
||||
MacroKind::Bang =>
|
||||
find_best_match_for_name(self.macro_names.iter(), name, None),
|
||||
MacroKind::Attr |
|
||||
MacroKind::Derive => {
|
||||
// Find a suggestion from the legacy namespace.
|
||||
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
|
||||
let builtin_macros = self.builtin_macros.clone();
|
||||
let names = builtin_macros.iter().filter_map(|(name, binding)| {
|
||||
if binding.get_macro(self).kind() == kind {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
find_best_match_for_name(names, name, None)
|
||||
// First check if this is a locally-defined bang macro.
|
||||
let suggestion = if let MacroKind::Bang = kind {
|
||||
find_best_match_for_name(self.macro_names.iter(), name, None)
|
||||
} else {
|
||||
None
|
||||
// Then check builtin macros.
|
||||
}.or_else(|| {
|
||||
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
|
||||
let builtin_macros = self.builtin_macros.clone();
|
||||
let names = builtin_macros.iter().filter_map(|(name, binding)| {
|
||||
if binding.get_macro(self).kind() == kind {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
find_best_match_for_name(names, name, None)
|
||||
// Then check modules.
|
||||
}).or_else(|| {
|
||||
if !self.use_extern_macros {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let is_macro = |def| {
|
||||
if let Def::Macro(_, def_kind) = def {
|
||||
def_kind == kind
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
let ident = Ident::from_str(name);
|
||||
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
|
||||
.as_ref().map(|s| Symbol::intern(s))
|
||||
});
|
||||
|
||||
if let Some(suggestion) = suggestion {
|
||||
if suggestion != name {
|
||||
if let MacroKind::Bang = kind {
|
||||
@ -566,7 +580,7 @@ impl<'a> Resolver<'a> {
|
||||
});
|
||||
self.macro_exports.push(Export {
|
||||
name: def.ident.name,
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id)),
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id), MacroKind::Bang),
|
||||
});
|
||||
self.exported_macros.push(def);
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
Def::AssociatedTy(..) |
|
||||
Def::AssociatedConst(..) |
|
||||
Def::PrimTy(_) |
|
||||
Def::Macro(_) |
|
||||
Def::Macro(..) |
|
||||
Def::Err => {
|
||||
span_bug!(span,
|
||||
"process_def_kind for unexpected item: {:?}",
|
||||
|
@ -199,7 +199,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
self.inside_public_path = orig_inside_public_path;
|
||||
if let Some(exports) = self.cx.export_map.get(&id) {
|
||||
for export in exports {
|
||||
if let Def::Macro(def_id) = export.def {
|
||||
if let Def::Macro(def_id, ..) = export.def {
|
||||
if def_id.krate == LOCAL_CRATE {
|
||||
continue // These are `krate.exported_macros`, handled in `self.visit()`.
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ pub type BuiltinDeriveFn =
|
||||
for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
|
||||
|
||||
/// Represents different kinds of macro invocations that can be resolved.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum MacroKind {
|
||||
/// A bang macro - foo!()
|
||||
Bang,
|
||||
|
@ -22,15 +22,24 @@ extern crate attr_proc_macro;
|
||||
|
||||
use attr_proc_macro::attr_proc_macro;
|
||||
|
||||
#[derive(FooWithLongNam)]
|
||||
//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope
|
||||
macro_rules! FooWithLongNam {
|
||||
() => {}
|
||||
}
|
||||
|
||||
#[derive(FooWithLongNan)]
|
||||
//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope
|
||||
//~^^ HELP did you mean `FooWithLongName`?
|
||||
struct Foo;
|
||||
|
||||
#[attr_proc_macra]
|
||||
//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope
|
||||
//~^^ HELP did you mean `attr_proc_macro`?
|
||||
struct Bar;
|
||||
|
||||
#[FooWithLongNan]
|
||||
//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope
|
||||
struct Asdf;
|
||||
|
||||
#[derive(Dlone)]
|
||||
//~^ ERROR cannot find derive macro `Dlone` in this scope
|
||||
//~^^ HELP did you mean `Clone`?
|
||||
@ -41,4 +50,18 @@ struct A;
|
||||
//~^^ HELP did you mean `Clona`?
|
||||
struct B;
|
||||
|
||||
fn main() {}
|
||||
#[derive(attr_proc_macra)]
|
||||
//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope
|
||||
struct C;
|
||||
|
||||
fn main() {
|
||||
FooWithLongNama!();
|
||||
//~^ ERROR cannot find macro `FooWithLongNama!` in this scope
|
||||
//~^^ HELP did you mean `FooWithLongNam!`?
|
||||
|
||||
attr_proc_macra!();
|
||||
//~^ ERROR cannot find macro `attr_proc_macra!` in this scope
|
||||
|
||||
Dlona!();
|
||||
//~^ ERROR cannot find macro `Dlona!` in this scope
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user