The most obvious way to shoot yourself in the foot is to have enums whose variants have the same names:
#[derive(Clone, Copy)]
enum RadioState {
Disabled,
BluetoothOnly,
WifiOnly,
Enabled,
}
#[derive(Clone, Copy)]
enum WifiConfig {
Disabled,
ClientOnly,
ApOnly,
Enabled,
}
fn configure_wireless(interface: &mut WifiInterface, rfkill: RadioState, wifi_config: WifiConfig) {
…
}
If I call configure_wireless(&mut interface, Enabled, Disabled)
, meaning configure_wireless(&mut interface, WifiConfig::Enabled, RadioState::Disabled)
, your change means that the code compiles, even though it doesn't match what I intend. Writing out the full types correctly causes the compiler to reject the code.
And the dialect trouble C++ has is that it has enough of this sort of feature that lets you write shorter, footgunny code that different projects have non-overlapping dialects of C++; some would require me to write configure_wireless(&mut interface, Enabled, Disabled)
, because I must always use the short form, others would require me to write configure_wireless(&mut interface, RadioState::Enabled, WifiConfig::Disabled)
because of the potential for ambiguity.
There is value in consistency, and value in keeping the language small; one of the things any proposal has to do is convince people that what it offers is more valuable than keeping the language small and consistent. There are two ways to do this:
- This feature is sufficiently valuable in its own right that no-one will lint against it; writing
#[doc="A documentation string"]
as /// A documentation string
is an example here. Less obviously true, but still the case is async
blocks as an easier way to implement std::future::Future
than manually implementing poll
correctly.
- The ability the feature enables is so valuable that we want it, even though people will lint against it. For example,
unsafe
fits this category; there are useful programs we cannot express without unsafe
blocks; but people still use #[forbid(unsafe_code)]
to lint against it.
In the case of your proposal, code is harder to read without an IDE, because when I see foo(::Disabled)
(or foo(_::Disabled)
), I have to look up the type signature of foo
to work out what enum it's referring to. If I do have an IDE, then it can automatically put the enum prefix in there for me (rust-analyzer in VSCode certainly puts it in the autocomplete prompts), and could hide it from me if I don't want to see it.
Given this, how would you justify this as a language feature, rather than an IDE feature?