Skip to content

Commit da6dc53

Browse files
Add macro suggestions for macros imported with use
This commit searchs modules for macro suggestions. It also removes imported macro_rules from macro_names, and adds more corner case checks for which macros should be suggested in specific contexts.
1 parent 4ecdc68 commit da6dc53

File tree

4 files changed

+64
-28
lines changed

4 files changed

+64
-28
lines changed

src/librustc_resolve/build_reduced_graph.rs

-1
Original file line numberDiff line numberDiff line change
@@ -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

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

@@ -2326,8 +2326,9 @@ impl<'a> Resolver<'a> {
23262326
};
23272327
}
23282328
}
2329-
if primary_ns != MacroNS && path.len() == 1 &&
2330-
self.macro_names.contains(&path[0].name) {
2329+
let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
2330+
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
2331+
if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
23312332
// Return some dummy definition, it's enough for error reporting.
23322333
return Some(
23332334
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))

src/librustc_resolve/macros.rs

+34-21
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,9 +152,6 @@ 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()),
@@ -466,24 +463,40 @@ impl<'a> Resolver<'a> {
466463

467464
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
468465
err: &mut DiagnosticBuilder<'a>) {
469-
let suggestion = match kind {
470-
MacroKind::Bang =>
471-
find_best_match_for_name(self.macro_names.iter(), name, None),
472-
MacroKind::Attr |
473-
MacroKind::Derive => {
474-
// Find a suggestion from the legacy namespace.
475-
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
476-
let builtin_macros = self.builtin_macros.clone();
477-
let names = builtin_macros.iter().filter_map(|(name, binding)| {
478-
if binding.get_macro(self).kind() == kind {
479-
Some(name)
480-
} else {
481-
None
482-
}
483-
});
484-
find_best_match_for_name(names, name, None)
466+
// First check if this is a locally-defined bang macro.
467+
let suggestion = if let MacroKind::Bang = kind {
468+
find_best_match_for_name(self.macro_names.iter(), name, None)
469+
} else {
470+
None
471+
// Then check builtin macros.
472+
}.or_else(|| {
473+
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
474+
let builtin_macros = self.builtin_macros.clone();
475+
let names = builtin_macros.iter().filter_map(|(name, binding)| {
476+
if binding.get_macro(self).kind() == kind {
477+
Some(name)
478+
} else {
479+
None
480+
}
481+
});
482+
find_best_match_for_name(names, name, None)
483+
// Then check modules.
484+
}).or_else(|| {
485+
if !self.use_extern_macros {
486+
return None;
485487
}
486-
};
488+
let is_macro = |def| {
489+
if let Def::Macro(_, def_kind) = def {
490+
def_kind == kind
491+
} else {
492+
false
493+
}
494+
};
495+
let ident = Ident::from_str(name);
496+
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
497+
.as_ref().map(|s| Symbol::intern(s))
498+
});
499+
487500
if let Some(suggestion) = suggestion {
488501
if suggestion != name {
489502
if let MacroKind::Bang = kind {

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)