This is a tracking issue for the RFC "impl-only-use " (rust-lang/rfcs#2166).
Steps:
I'm going to implement it this weekend.
I was thinking about this RFC recently. I wonder if we should enable users of existing preludes to take advantage of this feature. For example, for back-compat reasons, the Rayon prelude cannot change to export _, but I wonder if on the other side we could support some notation like use rayon::prelude::* as _ -- or is that too weird?
(Note that -- with the feature as currently implemented at least -- preludes can have pub use Trait as _; and that will get picked up by a glob import.)
One deficiency of the current implementation is that _ in use Trait as _ is not hygienic.
Normal trait imports generated by macros produce the next error that doesn't happen with _.
#![feature(decl_macro)]
#![allow(unused)]
struct S;
mod m {
pub trait Tr {
fn f(&self) {}
}
impl Tr for ::S {}
}
pub macro m() {
use m::Tr;
}
m!();
fn main() {
S.f(); // ERROR no method named `f` found for type `S` in the current scope
}
This is going to be fixed by https://github.com/rust-lang/rust/pull/48842 or equivalent.
@petrochenkov
You are saying that if we alter the macro in your example to this:
pub macro m() {
use m::Tr as _;
}
then the code will compile, right? (And that is the problem?)
In general, it seems sort of unclear whether one would expect this to work, but I guess consistency is good.
This is going to be fixed by #48842 or equivalent.
Why would that fix the problem?
@nikomatsakis
You are saying that if we alter the macro in your example to this ... then the code will compile, right?
Yes.
Why would that fix the problem?
Due to attaching hygiene context to _ (https://github.com/rust-lang/rust/pull/48842#issuecomment-373215752).
Actually, everything is more interesting - this bug is hidden by another bug!
Currently there's no way to use a trait in macro so that its methods are in scope after expansion of that macro.
Nothing of this works:
pub macro outer_use1($Rename: ident) {
use m::Tr as $Rename;
}
pub macro outer_use2($Tr: ident) {
use m::$Tr;
}
pub macro outer_use3($Tr: path) {
pub use $Tr;
}
outer_use1!(Rename);
outer_use2!(Tr);
outer_use3!(m::Tr);
// still a "no method named `f`" error after expanding all the macros above
S.f();
I just ran into an interesting corner case: if I write use somecrate as _;, that produces an unused_imports warning:
warning: unused import: `somecrate as _`
That seems wrong; use somecrate as _ should pull in somecrate even if the module doesn't use any of its symbols, such as for the purposes of linking, allocators, etc.
That bug is not limited to as _: if you write use std::io as _io; on stable, it warns.
Working on fixing this.
https://github.com/rust-lang/rust/pull/53479 should fix this for extern crate foo as _; or extern crate foo as _bar;.
For searchability: this is the unstable feature underscore_imports
Nominating for discussion of Rust 2018-only stabilization at the next @rust-lang/lang meeting.
@eddyb I would suggest preparing a "stabilization report" that contains summary of what behavior is to be stabilized, what corner cases were uncovered, what changed with respect to the RFC, etc. Given that you wrote "Rust 2018-only" that seems to imply to me that there have been some corner cases or other things discovered? Or some interaction with the module system changes?
It seems like the behavior is the same when you use macro_rules!, presumably because of hygiene. e.g., this works either with or without _:
#![feature(decl_macro)]
#![feature(underscore_imports)]
#![allow(unused)]
struct S;
mod m {
pub trait Tr {
fn f(&self) {}
}
impl Tr for ::S {}
}
macro_rules! m {
() => {
use m::Tr as _;
}
}
m!();
fn main() {
S.f(); // ERROR no method named `f` found for type `S` in the current scope
}
decl macros are not stable, so I guess the hygiene interactions there don't matter too much.
@nikomatsakis Sadly I am not as informed as @petrochenkov on this feature.
But https://github.com/rust-lang/rust/issues/48216#issuecomment-373664699 appears to be fixed on nightly.
I don't think we need to stabilize yet, but allowing use crate_name as _; in the new edition seems necessary in some situations (e.g. when you want to link against a crate but not use items from it).
However, if we make use foo as _foo; not warn when foo is a crate, then that's fine too.
If possible, I'd like for this feature to be included in Rust 2015 as well.
Are there any blockers / problems with doing that?
The hygiene problem doesn't seem to actually matter per https://github.com/rust-lang/rust/issues/48216#issuecomment-415547904.
I'm not aware of any issues preventing stabilization of this on Rust 2015.
as _ and all the other module/import stuff reformed in 2018 are pretty much orthogonal.
The hygiene issues appear only if we have both call-site and def-site hygiene, so they affect only nightly.
@petrochenkov Since you are most informed about this, could you prepare a stabilization report for this for both Rust 2015 and Rust 2018?
@petrochenkov any progress?
It's in the queue, but with lower priority than uniform paths.
Stabilization report + stabilization PR - https://github.com/rust-lang/rust/pull/56303.
Most helpful comment
@eddyb I would suggest preparing a "stabilization report" that contains summary of what behavior is to be stabilized, what corner cases were uncovered, what changed with respect to the RFC, etc. Given that you wrote "Rust 2018-only" that seems to imply to me that there have been some corner cases or other things discovered? Or some interaction with the module system changes?