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

use foo::{self, ...} doesn't import macro foo! #63842

Closed
valff opened this issue Aug 24, 2019 · 8 comments
Closed

use foo::{self, ...} doesn't import macro foo! #63842

valff opened this issue Aug 24, 2019 · 8 comments
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@valff
Copy link
Contributor

valff commented Aug 24, 2019

When there is a macro and a module with the same name, use foo::{self, Bar} syntax imports the module foo, but not the macro foo!. So you are forced to use this:

use crate::foo;
use crate::foo::Bar;

It is especially annoying because rustfmt automatically merges it like this:

use crate::foo::{self, Bar};

And the macro is no longer imported. Both procedural and declarative macros are affected. Here is the full example:

pub mod foo {
    pub struct Bar;
}

mod inner {
    use crate::foo::{self, Bar};
    foo!();
}

#[macro_export]
macro_rules! foo {
    () => {};
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: cannot find macro `foo!` in this scope
 --> src/lib.rs:7:5
  |
7 |     foo!();
  |     ^^^
  |
  = help: have you added the `#[macro_use]` on the module/import?

warning: unused imports: `Bar`, `self`
 --> src/lib.rs:6:22
  |
6 |     use crate::foo::{self, Bar};
  |                      ^^^^  ^^^
  |
  = note: #[warn(unused_imports)] on by default

error: aborting due to previous error

error: Could not compile `playground`.

To learn more, run the command again with --verbose.

@ehuss
Copy link
Contributor

ehuss commented Aug 24, 2019

According to #60941 (comment), this is working as intended.

@valff
Copy link
Contributor Author

valff commented Aug 24, 2019

Hm. So considering a use statement as a tree, the leaves except self import modules, functions and macros, but a self leaf imports only modules. But what are the benefits of this asymmetry?

@valff
Copy link
Contributor Author

valff commented Aug 24, 2019

There is a precedent in stdlib with std::vec! macro and std::vec::Vec struct. If they wouldn't be in the prelude, we wouldn't be able to use the single import statement use std::vec::{self, Vec}.

@jonas-schievink
Copy link
Contributor

Closing as per #60941 (comment). Changes to this would likely require an RFC.

@ehuss
Copy link
Contributor

ehuss commented Aug 24, 2019

I'm not sure, @petrochenkov will need to clarify.

There is a sort of consistency. If path segments are processed in sequence, the resolver only needs to track which module has been resolved until the leaf. If it allowed self to import multiple things, then it would also need to track all things found along the path (or backtrack), both of which sound more difficult and complicated. It would also make self in a leaf position a special case, adding an exception to the rules.

It also has a consistency with super and crate which only resolve modules.

I agree it is a bit surprising. My mental model used to be that use foo::{self, Bar}; is syntactic sugar for use foo; use foo::Bar;, but that is not how it works.

@jonas-schievink jonas-schievink added A-resolve Area: Name/path resolution done by `rustc_resolve` specifically T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Aug 24, 2019
@valff
Copy link
Contributor Author

valff commented Aug 24, 2019

@ehuss Thanks for the explanation!

What is also confusing, if I want to import both the module and the macro, this doesn't work:

use std::vec::{self, Vec};
use std::vec; // I want just the macro here

It adds too much friction to using imports. I need to maintain two groups of imports: for macros and for other things. And I need to ensure they are not overlapping.

@sinkuu
Copy link
Contributor

sinkuu commented Aug 24, 2019

use std::{vec, vec::Vec}?

@valff
Copy link
Contributor Author

valff commented Aug 24, 2019

Yeah, I had to add that I want to use rust-lang/rustfmt#3362. And there should be a blank line between those two imports, so they are not merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants