Rust: `use some::module::self;` and `use some::module;` not semantically equivalent

Created on 18 May 2019  路  5Comments  路  Source: rust-lang/rust

In instances where a path can represent both a module and a function or macro, the self import will only import the module and not the function/macro, whereas everything will be imported if the use statement ends with just the module/macro/function name.

This causes issues with rustfmt's merge_imports option: https://github.com/rust-lang/rustfmt/issues/3362

If rustc is "working as intended," the behavior is such that merge_imports will never be able to safely create self imports.

T-lang

Most helpful comment

I'm with @gnzlbg; this seems unnecessarily confusing. Intuitively, use something::{self}; should be the same as use something;, and I feel like that's how the vast majority of people interpret the syntax. It's going to get extra weird when people start taking imports like

use foo::{
    self,
    bar,
    baz,
};

, delete bar and baz, and then get confused when rustfmt does the right thing and leaves them with use foo::{self};. At least the opposite case with merge_imports = true (use foo::bar; use foo::baz; use foo -> use foo; use foo::{bar, baz};[^1]) doesn't look obviously wrong.

Edit: use foo::{self}; seems especially wrong considering that use foo::self; isn't allowed.

Also, it seems inconsistent since I don't see an obvious way to get at just a function or macro, while you can get only the module with self imports.

All 5 comments

@petrochenkov might know about this

@Nemo157 referred me to this issue that came up before, but I couldn't find any reference in any of the linked issues to how self imports are supposed to be treated.

This is working as intended :)

The thing before :: (e.g. foo in foo::bar or foo::self) is always a type/module, so path resolutions can never "bifurcate" in the middle, so a path can resolve to 3 things at most, determined entirely by the last segment.

@petrochenkov This feels like a big subtlety in how imports work, could we do better here, or what's the value of this distinction and how does it outweigh its costs in terms of teachability?

For example, when the last component of a path is self, the previous component is interpreted as "any item", and if multiple items with the same name are found, all of them are imported.

I'm with @gnzlbg; this seems unnecessarily confusing. Intuitively, use something::{self}; should be the same as use something;, and I feel like that's how the vast majority of people interpret the syntax. It's going to get extra weird when people start taking imports like

use foo::{
    self,
    bar,
    baz,
};

, delete bar and baz, and then get confused when rustfmt does the right thing and leaves them with use foo::{self};. At least the opposite case with merge_imports = true (use foo::bar; use foo::baz; use foo -> use foo; use foo::{bar, baz};[^1]) doesn't look obviously wrong.

Edit: use foo::{self}; seems especially wrong considering that use foo::self; isn't allowed.

Also, it seems inconsistent since I don't see an obvious way to get at just a function or macro, while you can get only the module with self imports.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

behnam picture behnam  路  3Comments

pedrohjordao picture pedrohjordao  路  3Comments

dtolnay picture dtolnay  路  3Comments

Robbepop picture Robbepop  路  3Comments

wthrowe picture wthrowe  路  3Comments