Skip to content

Commit fb3836a

Browse files
authored
Rollup merge of rust-lang#39953 - keeperofdakeys:macro-error, r=jseyfried
Provide suggestions for unknown macros imported with `use` cc rust-lang#30197 r? @jseyfried
2 parents 9273c89 + da6dc53 commit fb3836a

File tree

9 files changed

+92
-43
lines changed

9 files changed

+92
-43
lines changed

src/librustc/hir/def.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use hir::def_id::DefId;
1212
use util::nodemap::NodeMap;
1313
use syntax::ast;
14+
use syntax::ext::base::MacroKind;
1415
use hir;
1516

1617
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -53,7 +54,7 @@ pub enum Def {
5354
Label(ast::NodeId),
5455

5556
// Macro namespace
56-
Macro(DefId),
57+
Macro(DefId, MacroKind),
5758

5859
// Both namespaces
5960
Err,
@@ -141,7 +142,7 @@ impl Def {
141142
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
142143
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
143144
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
144-
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => {
145+
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
145146
id
146147
}
147148

src/librustc_metadata/decoder.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
3939
use syntax::attr;
4040
use syntax::ast;
4141
use syntax::codemap;
42+
use syntax::ext::base::MacroKind;
4243
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
4344

4445
pub struct DecodeContext<'a, 'tcx: 'a> {
@@ -434,7 +435,7 @@ impl<'tcx> EntryKind<'tcx> {
434435
EntryKind::Variant(_) => Def::Variant(did),
435436
EntryKind::Trait(_) => Def::Trait(did),
436437
EntryKind::Enum(..) => Def::Enum(did),
437-
EntryKind::MacroDef(_) => Def::Macro(did),
438+
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
438439

439440
EntryKind::ForeignMod |
440441
EntryKind::Impl(_) |
@@ -483,9 +484,11 @@ impl<'a, 'tcx> CrateMetadata {
483484
}
484485

485486
pub fn get_def(&self, index: DefIndex) -> Option<Def> {
486-
match self.is_proc_macro(index) {
487-
true => Some(Def::Macro(self.local_def_id(index))),
488-
false => self.entry(index).kind.to_def(self.local_def_id(index)),
487+
if !self.is_proc_macro(index) {
488+
self.entry(index).kind.to_def(self.local_def_id(index))
489+
} else {
490+
let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind();
491+
Some(Def::Macro(self.local_def_id(index), kind))
489492
}
490493
}
491494

@@ -688,8 +691,14 @@ impl<'a, 'tcx> CrateMetadata {
688691
{
689692
if let Some(ref proc_macros) = self.proc_macros {
690693
if id == CRATE_DEF_INDEX {
691-
for (id, &(name, _)) in proc_macros.iter().enumerate() {
692-
let def = Def::Macro(DefId { krate: self.cnum, index: DefIndex::new(id + 1) });
694+
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
695+
let def = Def::Macro(
696+
DefId {
697+
krate: self.cnum,
698+
index: DefIndex::new(id + 1)
699+
},
700+
ext.kind()
701+
);
693702
callback(def::Export { name: name, def: def });
694703
}
695704
}

src/librustc_resolve/build_reduced_graph.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ impl<'a> Resolver<'a> {
495495

496496
pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
497497
let def_id = match def {
498-
Def::Macro(def_id) => def_id,
498+
Def::Macro(def_id, ..) => def_id,
499499
_ => panic!("Expected Def::Macro(..)"),
500500
};
501501
if let Some(ext) = self.macro_map.get(&def_id) {
@@ -537,7 +537,6 @@ impl<'a> Resolver<'a> {
537537
binding: &'a NameBinding<'a>,
538538
span: Span,
539539
allow_shadowing: bool) {
540-
self.macro_names.insert(name);
541540
if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
542541
let msg = format!("`{}` is already in scope", name);
543542
let note =

src/librustc_resolve/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,7 @@ impl<'a> Resolver<'a> {
12651265
ribs: PerNS {
12661266
value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
12671267
type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
1268-
macro_ns: None,
1268+
macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]),
12691269
},
12701270
label_ribs: Vec::new(),
12711271

@@ -2328,10 +2328,13 @@ impl<'a> Resolver<'a> {
23282328
};
23292329
}
23302330
}
2331-
if primary_ns != MacroNS && path.len() == 1 &&
2332-
self.macro_names.contains(&path[0].name) {
2331+
let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
2332+
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
2333+
if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
23332334
// Return some dummy definition, it's enough for error reporting.
2334-
return Some(PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX))));
2335+
return Some(
2336+
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
2337+
);
23352338
}
23362339
fin_res
23372340
}

src/librustc_resolve/macros.rs

+37-23
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use syntax::ast::{self, Name, Ident};
2323
use syntax::attr;
2424
use syntax::errors::DiagnosticBuilder;
2525
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
26-
use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
26+
use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
2727
use syntax::ext::base::MacroKind;
2828
use syntax::ext::expand::{Expansion, mark_tts};
2929
use syntax::ext::hygiene::Mark;
@@ -152,16 +152,14 @@ impl<'a> base::Resolver for Resolver<'a> {
152152
}
153153

154154
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
155-
if let NormalTT(..) = *ext {
156-
self.macro_names.insert(ident.name);
157-
}
158155
let def_id = DefId {
159156
krate: BUILTIN_MACROS_CRATE,
160157
index: DefIndex::new(self.macro_map.len()),
161158
};
159+
let kind = ext.kind();
162160
self.macro_map.insert(def_id, ext);
163161
let binding = self.arenas.alloc_name_binding(NameBinding {
164-
kind: NameBindingKind::Def(Def::Macro(def_id)),
162+
kind: NameBindingKind::Def(Def::Macro(def_id, kind)),
165163
span: DUMMY_SP,
166164
vis: ty::Visibility::Invisible,
167165
expansion: Mark::root(),
@@ -470,24 +468,40 @@ impl<'a> Resolver<'a> {
470468

471469
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
472470
err: &mut DiagnosticBuilder<'a>) {
473-
let suggestion = match kind {
474-
MacroKind::Bang =>
475-
find_best_match_for_name(self.macro_names.iter(), name, None),
476-
MacroKind::Attr |
477-
MacroKind::Derive => {
478-
// Find a suggestion from the legacy namespace.
479-
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
480-
let builtin_macros = self.builtin_macros.clone();
481-
let names = builtin_macros.iter().filter_map(|(name, binding)| {
482-
if binding.get_macro(self).kind() == kind {
483-
Some(name)
484-
} else {
485-
None
486-
}
487-
});
488-
find_best_match_for_name(names, name, None)
471+
// First check if this is a locally-defined bang macro.
472+
let suggestion = if let MacroKind::Bang = kind {
473+
find_best_match_for_name(self.macro_names.iter(), name, None)
474+
} else {
475+
None
476+
// Then check builtin macros.
477+
}.or_else(|| {
478+
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
479+
let builtin_macros = self.builtin_macros.clone();
480+
let names = builtin_macros.iter().filter_map(|(name, binding)| {
481+
if binding.get_macro(self).kind() == kind {
482+
Some(name)
483+
} else {
484+
None
485+
}
486+
});
487+
find_best_match_for_name(names, name, None)
488+
// Then check modules.
489+
}).or_else(|| {
490+
if !self.use_extern_macros {
491+
return None;
489492
}
490-
};
493+
let is_macro = |def| {
494+
if let Def::Macro(_, def_kind) = def {
495+
def_kind == kind
496+
} else {
497+
false
498+
}
499+
};
500+
let ident = Ident::from_str(name);
501+
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
502+
.as_ref().map(|s| Symbol::intern(s))
503+
});
504+
491505
if let Some(suggestion) = suggestion {
492506
if suggestion != name {
493507
if let MacroKind::Bang = kind {
@@ -566,7 +580,7 @@ impl<'a> Resolver<'a> {
566580
});
567581
self.macro_exports.push(Export {
568582
name: def.ident.name,
569-
def: Def::Macro(self.definitions.local_def_id(def.id)),
583+
def: Def::Macro(self.definitions.local_def_id(def.id), MacroKind::Bang),
570584
});
571585
self.exported_macros.push(def);
572586
}

src/librustc_save_analysis/dump_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
336336
Def::AssociatedTy(..) |
337337
Def::AssociatedConst(..) |
338338
Def::PrimTy(_) |
339-
Def::Macro(_) |
339+
Def::Macro(..) |
340340
Def::Err => {
341341
span_bug!(span,
342342
"process_def_kind for unexpected item: {:?}",

src/librustdoc/visit_ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
199199
self.inside_public_path = orig_inside_public_path;
200200
if let Some(exports) = self.cx.export_map.get(&id) {
201201
for export in exports {
202-
if let Def::Macro(def_id) = export.def {
202+
if let Def::Macro(def_id, ..) = export.def {
203203
if def_id.krate == LOCAL_CRATE {
204204
continue // These are `krate.exported_macros`, handled in `self.visit()`.
205205
}

src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ pub type BuiltinDeriveFn =
475475
for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
476476

477477
/// Represents different kinds of macro invocations that can be resolved.
478-
#[derive(Clone, Copy, PartialEq, Eq)]
478+
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
479479
pub enum MacroKind {
480480
/// A bang macro - foo!()
481481
Bang,

src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,24 @@ extern crate attr_proc_macro;
2222

2323
use attr_proc_macro::attr_proc_macro;
2424

25-
#[derive(FooWithLongNam)]
26-
//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope
25+
macro_rules! FooWithLongNam {
26+
() => {}
27+
}
28+
29+
#[derive(FooWithLongNan)]
30+
//~^ ERROR cannot find derive macro `FooWithLongNan` in this scope
2731
//~^^ HELP did you mean `FooWithLongName`?
2832
struct Foo;
2933

3034
#[attr_proc_macra]
3135
//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope
36+
//~^^ HELP did you mean `attr_proc_macro`?
3237
struct Bar;
3338

39+
#[FooWithLongNan]
40+
//~^ ERROR cannot find attribute macro `FooWithLongNan` in this scope
41+
struct Asdf;
42+
3443
#[derive(Dlone)]
3544
//~^ ERROR cannot find derive macro `Dlone` in this scope
3645
//~^^ HELP did you mean `Clone`?
@@ -41,4 +50,18 @@ struct A;
4150
//~^^ HELP did you mean `Clona`?
4251
struct B;
4352

44-
fn main() {}
53+
#[derive(attr_proc_macra)]
54+
//~^ ERROR cannot find derive macro `attr_proc_macra` in this scope
55+
struct C;
56+
57+
fn main() {
58+
FooWithLongNama!();
59+
//~^ ERROR cannot find macro `FooWithLongNama!` in this scope
60+
//~^^ HELP did you mean `FooWithLongNam!`?
61+
62+
attr_proc_macra!();
63+
//~^ ERROR cannot find macro `attr_proc_macra!` in this scope
64+
65+
Dlona!();
66+
//~^ ERROR cannot find macro `Dlona!` in this scope
67+
}

0 commit comments

Comments
 (0)