Problem
As we know in Rust there's a tendency to switch from bool
to appropriately named enums, for example:
enum Something {
Enabled(data),
Disabled,
}
then we use if let
expressions instead of if bool
, which provides more context:
if let Something::Enabled(data) = something {
...
}
The problem is that in expressions like that enums must be imported first if they're defined in a different module or crate. Hence the above expression must be a bit more complicated:
use path_to_something::Something;
if let Something::Enabled(data) = something {
...
}
Another problem is that we must decide where to put this use
statement: at the top of module or locally where an imported enum is used; local is better, but autocompletion always places items at the top.
Prior art
There have been proposals to automatically import enum variants in scope of patterns as well as to introduce a shortcut like _::Something(data)
— both can solve problems with use
statements easily. But they also introduces another set of problems either with implicitness or noisiness that not everyone likes to have.
And both proposals removes enum name, against which there have been many objections.
Solution
I propose use _::EnumName;
syntax which could be use _::Struct;
as well. It means that path to enum/struct has been inferred from context, so the above if let
expression would be:
use _::Something;
if let Something::Enabled(data) = something {
...
}
There should be lints if such use
statement is placed far away from usage of imported item. Also, placing such use
statements shouldn't be possible in top level declarations for example at the top of module.
Advantages
Perhaps people would say that saving a few symbols is not worth the churn. But in fact there are other advantages in this way of writing the code:
- It gives an opportunity to introduce alias like
use _::Something as Smth
to shorten enum name- This promotes to avoid glob-use e.g.
use path_to_module::Something::*
- This promotes to avoid glob-use e.g.
- It as well promotes to place
use
statements locally- This improves local reasoning because there's no need to refer to the top of module
- This also improves local reasoning because with
_::
we seek for the value from which path is inferred - And removes
use
statements from the top of module where currently IMO is a mess
- Better code alignment with
if let
Drawbacks
-
Obviously, it's another language item which should be implemented and taught to users.
-
Besides of that there's an opportunity to place it too far away from usage, which could make code too obscure.
-
Things like
use _::Something as S
looks quite verbose and complicated. -
Also, placing multiple such
use
statements in a row looks bad, perhaps there should be a shortcut like:use _::{Something, SomethingFromOtherModule}