Closed alexcrichton closed 6 years ago
cc @Manishearth
I and @nikomatsakis discussed this a bunch when implementing this and decided not to fix this problem. An earlier commit of mine there had an attempt which would try and ask you to directly import crates when used as use (0+ local modules in chain)::cratename::(optional foo)
. It's tricky to get right though. I can dig up the commit if we want that.
The fix is in https://github.com/Manishearth/rust/commit/c904d98bc59c17e61332f1d2179ebe3b920835be
It's not perfect for a bunch of reasons (also might not do precisely what I said in the commit above, but close)
While I can't say for sure I'd be pretty certain that this pattern shows up in the wild (especially use foo::krate_name::bar
). If we go with the status quo then it means crates with this pattern won't be able to use rustfix as currently it's an all-or-nothing wrt fixes. Given the experience I've had so far with rustfix I think we want to strive for the highest fidelity lints we can which to me means that we'll likely want to fix this.
Okay, so paging this in a bit more, while https://github.com/Manishearth/rust/commit/c904d98bc59c17e61332f1d2179ebe3b920835be is a pretty decent lint, we can't write suggestions for it. The problem is that use trees get split out in HIR, which means that the suggestions here can't work to well in the presence of these. It's hard to even detect that there's a use tree involved (in some cases)
Also, doing the span-splicing to emit the correct suggestion is tricky as well, we don't store spans for path segments.
So basically this is doable as a rustfixable lint, but it will be buggy and/or very imperfect.
I have a few questions. My memory is that, when an extern crate
appears somewhere other than the crate root, we are going to leave it in place, and let the user fix it manually.
However, if the extern crate
appeared at the crate root, we would remove it, and then try not to rewrite paths like use foo::bar
(which is technically accessing crate::foo::bar
today, so to speak).
This approach breaks if the code uses use crate::foo::bar
, but that's not a common pattern today. But where else does it break?
One answer to my question would be use self::foo::bar
or use super::foo::bar
.
I am reminded that I initially wanted to do a kind of global pass to see where and how the extern crate
was used, and only suggest removing it if it is not used from paths like those above. I'm not sure how easy/hard that would be to do but it seems like it would address this issue.
OK, so, it seems like the lint that @Manishearth pointed us at (https://github.com/Manishearth/rust/commit/c904d98bc59c17e61332f1d2179ebe3b920835be) does the following:
use self::foo
) and warns about it.As @Manishearth said, writing suggestions for this case is tricky, at least in its full generality. But we could certainly do something like the following:
That means we'd suppress the "not actionable" error but issue lints that guide you towards making the extern crate into something we can remove.
However, there is still the downside that the paths must be manually changed. I suspect we can overcome that in practice a lot of the time — I mean there are tricky cases, but we can look for the plain vanilla case and just issue the suggestion in that case (for example, by checking that the span
of the use statement begins with use self::foo::bar::
or whatever).
I discussed with @nikomatsakis a bit on discord and agree that perhaps the best thing to do here is to avoid linting anything at all, but rather wait till the lint is higher accuracy to turn it on by default.
Pending fix in #51015
The following code
generates an error:
but if the
extern crate libc;
is removed it no longer compiles!This situation has come up on two occasions so far:
use libc;
and rustfix rewrote it touse crate::libc;
. This worked in the 2015 edition becauseextern crate libc;
was declared at the top. Later thisunnecessary_extern_crate
lint ended up showing the error above.use *;
statement is entirely disallowed in the 2018 edition, so we instead recommend the replacementuse crate::*;
. This, however, will also break if one of the identifiers used is anextern crate
as the lint currently suggests removingextern crate