Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide suggestions for unknown macros imported with use #39953

Merged
merged 2 commits into from
Feb 25, 2017

Conversation

keeperofdakeys
Copy link
Contributor

@petrochenkov
Copy link
Contributor

It looks like MacroKind is better moved into Def, this way you won't have to pass the resolver around.
Def is expected to be self-sufficient when deciding if some resolution is expected in some context or not.
I hope all this special code for macros will be replaced by using the common smart_resolve_path infrastructure later.

@petrochenkov
Copy link
Contributor

Def::Macro(DefId) -> Def::Macro(DefId, MacroKind) would be enough for a start, but in principle by-example macros and attribute macros are as different as, e.g., structs and traits, and expected in different contexts, so they could even have separate Def variants (this could be less convenient in practice though).

@jseyfried
Copy link
Contributor

It looks like MacroKind is better moved into Def
Def::Macro(DefId) -> Def::Macro(DefId, MacroKind)

Agreed, this looks like the cleanest solution -- thanks @petrochenkov!

@keeperofdakeys would you mind doing this instead of passing around the resolver more?

@keeperofdakeys
Copy link
Contributor Author

Sure, sounds like a good idea.

@keeperofdakeys
Copy link
Contributor Author

@jseyfried
Two questions:

  1. Is a syntax::ast::MacroDef always a macro_rules!? (If not I'll need to store a MacroKind in it).
  2. Does rustc_metadata::cstore::CrateMetadata.proc_macros only ever contain derive proc macros? (Otherwise it will need to be a (Name, MacroKind, SyntaxExtension)).

@jseyfried
Copy link
Contributor

jseyfried commented Feb 20, 2017

@keeperofdakeys

Is a syntax::ast::MacroDef always a macro_rules!?

Yes.

Does rustc_metadata::cstore::CrateMetadata.proc_macros only ever contain derive proc macros?

No, it can contain attribute proc macros today and bang proc macros once they are implemented.

(Otherwise it will need to be a (Name, MacroKind, SyntaxExtension))

Can't you get the MacroKind from the SyntaxExtension, so (Name, SyntaxExtension) is still sufficient?

@keeperofdakeys
Copy link
Contributor Author

keeperofdakeys commented Feb 20, 2017

I added some corner cases to the test cases, which I'm guessing were failing before all the changes in this PR. To fix it, I need to filter macro_names for only MacroKind::Bang. Can I use builtin_macros to check the syntax extension of these?

Also, are the changes to get_def correct?

@keeperofdakeys
Copy link
Contributor Author

So for some reason derive proc-macros are appearing in macro_names, which from what I know shouldn't be happening (attribute macros, and builtin derive macros do not). This is what is causing the test failure. I'll need to investigate whether this was caused by my changes here, or if this has always been the case.

}
unreachable!();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think this would be clearer as an if !self.is_proc_macro(index) { ... } else { ... } to avoid early returns.

Also, I would do let kind = self.proc_macros.as_ref().unwrap()[index.as_usize() - 1].1.kind(); in the else case to avoid unreachable!().

@@ -151,7 +151,7 @@ impl<'a> base::Resolver for Resolver<'a> {
invocation.expansion.set(visitor.legacy_scope);
}

fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
fn add_ext(&mut self, ident: ast::Ident, kind: MacroKind, ext: Rc<SyntaxExtension>) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have the SyntaxExtension, I don't think we need to add the MacroKind argument.

MacroKind::Attr |
MacroKind::Derive => {
kind @ MacroKind::Attr |
kind @ MacroKind::Derive => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no need to add kind @ here -- kind is already in scope.

@jseyfried
Copy link
Contributor

I need to filter macro_names for only MacroKind::Bang

macro_names was used for the legacy suggestion system, so I think we should put as few names as possible in it.
Specifically, I think it should only have crate-local macro_rules! macros -- all other macros will be in builtin_macros (built-ins, #![plugin(..)], #[macro_use]) or individual Modules (use).

It looks like we add to macro_names here, here, and here -- looks like we can remove the second two and just keep the first one.

@keeperofdakeys
Copy link
Contributor Author

@jseyfried Is the second place you told me to remove the insertion into macro_names correct? I suspect this is causing the current test failure. Do you think this is the cause? https://github.com/keeperofdakeys/rust/blob/928c6ee2e00cfddff8786209154ce986659218e1/src/librustc_resolve/lib.rs#L2329. Perhaps adding builting macros here as well might work? Or using resolve_macro(name, kind: MacroKind::Bang, false)?

@keeperofdakeys
Copy link
Contributor Author

Ah, I understand now. It was usually imported by the legacy_import function. For now I've added builtin_macros to the macro name check.

@jseyfried
Copy link
Contributor

For now I've added builtin_macros to the macro name check

Great, that's what I was going to suggest :)

@keeperofdakeys
Copy link
Contributor Author

I think all the issues have been fixed now, so feel free to merge if you're happy with it.

Copy link
Contributor

@jseyfried jseyfried left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent! All nits are optional.

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting nit: this line break here looks weird to me -- I'd put it all on one line or break after the ].

if let Some(binding) = binding {
contains = contains || binding.get_macro(self).kind() == MacroKind::Bang;
}
if primary_ns != MacroNS && path.len() == 1 && contains {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would write this as

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)) { ... }

find_best_match_for_name(self.macro_names.iter(), name, None)
} else {
None
// Then check the legacy namespace.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say "built-in macros' legacy namespace" or just "built-in macros" for clarity (I've referred to the scope of local macro_rules! as "legacy" in item names and in comments).

};
let ident = Ident::with_empty_ctxt(Symbol::intern(name));
self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
.map(|s| Symbol::intern(&s))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: .as_ref().map(Symbol::intern) might work here

false
}
};
let ident = Ident::with_empty_ctxt(Symbol::intern(name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Ident::from_str should do the trick here.

@jseyfried
Copy link
Contributor

@bors delegate=keeperofdakeys

@bors
Copy link
Contributor

bors commented Feb 22, 2017

✌️ @keeperofdakeys can now approve this pull request

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.
@keeperofdakeys
Copy link
Contributor Author

@bors r=jseyfried

@bors
Copy link
Contributor

bors commented Feb 23, 2017

📌 Commit da6dc53 has been approved by jseyfried

eddyb added a commit to eddyb/rust that referenced this pull request Feb 25, 2017
…ried

Provide suggestions for unknown macros imported with `use`

cc rust-lang#30197

r? @jseyfried
eddyb added a commit to eddyb/rust that referenced this pull request Feb 25, 2017
…ried

Provide suggestions for unknown macros imported with `use`

cc rust-lang#30197

r? @jseyfried
bors added a commit that referenced this pull request Feb 25, 2017
@bors bors merged commit da6dc53 into rust-lang:master Feb 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants