-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disambiguate enum variant names. #94
Conversation
Idea originated in this reddit thread: http://www.reddit.com/r/rust/comments/269zu4/add_a_new_language_design_faq/chp5k50 +1, unless someone points out a glaring flaw in name resolution or the like. It's very much surprising that something like This RFC would also appease everyone who was previously requesting cc @cmr |
Another (more radical) alternative would be to have variants only accessible under the type's namespace. |
We have discussed and rejected that idea in the past. This RFC acknowledges that both behaviors are desirable, and enables them without requiring any special syntax. Basically the only thing that this RFC lacks is the ability to enforce that a variant is always qualified with the enum's name, but I don't see this as an issue. |
So if I understand this correctly, it allows the path |
@kballard, while not an ambiguity in the syntactical sense, please note that this ambiguity exists today. Consider: enum IntList {
Node(int, Box<IntList>),
None
}
fn main() {
let x = Some(box None);
} Quick, off the top of your head: does this code compile? If so, what is the type of Answer: it does compile, and the type of Note that this isn't a contrived example, as I have personally observed people asking for help after triggering this exact scenario. Under this RFC, the above code would become a compiler error, and force you to disambiguate your variant usage. |
I should mention here that I'm not trying to derail us with a discussion of the merits of name shadowing, which doesn't exist only for enum variants. Take the following code, which compiles today: use foo::Qux;
use bar::Qux;
mod foo {
pub struct Qux(pub int);
}
mod bar {
pub struct Qux(pub uint);
}
fn main() {
let y = Qux(2);
} The type of |
@bstrie That can be disambiguated today by using The latter bit actually does concern me, though. Can enum variants collide with other things? Surely not, because the other value at that path would have no way of disambiguating itself. So this makes enum variants rather special in that they can collide with each other, but nothing else can collide. It deviates from the current strict rule that in the value namespace, a given path can only refer to a single value. In any case, with the The issue with variant collision seems a very strong reason to go for the |
To clarify; with this RFC, if I want a |
I'm not sure I understand your concerns regarding collision. To me, this RFC can be boiled down to the following two points:
Indeed, this will be a special case to our current name lookup rules. But it's a special case that makes the rules stricter, which is why I don't see the problem. Even if we just adopted the first point without the second, I think it would be a step in the right direction. |
Shadowing and colliding are different things. This RFC seems to assume that they're the same thing, but they're not. A fully-qualified path enum A {
X,
Y
}
enum B {
X,
Y
} has two The RFC seems to just assume that this is ok and that And without allowing collision, I don't think this RFC is actually doing anything, because as I said the fully-qualified path is always unambiguous. The only thing that I can think of that it would really affect is |
I was under the impression that there would be no implicit constructor injection in your given example. As in, there would be no Regardless, this doesn't have anything to do with the real thrust of this RFC, which is contained in the two points of my previous comment. I'm not sure what this has to do with |
@bstrie Really? Your impression is apparently what @sfackler said was an alternative approach, but is not in fact what this RFC is proposing. It's treating |
I admit that the "Detailed design" section is woefully underdetailed and I confess to taking the RFC's sentiment to its furthest conclusion. That said, the example given is "a simple case of enumeration disambiguation", and clearly not the only intended case. I would be happy to open a more detailed RFC if the author of this one is unresponsive. |
Here's a review of how I'm reading this RFC, and what the problems are with it. This is basically a summary of what I've said in response to @bstrie but hopefully putting it out on its own and not as a response will make it clearer: This RFC appears to be asking for enum variants to become a special case to the value namespace rules, in that two enum variants are explicitly allowed to collide. This isn't expanded upon anywhere in the detailed description, but it's the only way to interpret the summary, and it's the only behavior that makes the rest of the RFC make sense. This alone gives me cause for concern. Right now we have a strict rule where two values cannot collide (just as two types cannot collide). Values can shadow each other, as long as they live at different paths, and the shadowing is due to how name resolution works. But shadowing and collision are different, and this RFC is strictly concerned with collision. Assuming the collision is allowed, this then proposes that the variants can be disambiguated by using the enum name as if it were a module, e.g. Of course, even treating this like a In any case, we may end up with associated values at some point, but we don't have them today. A non-nullary enum variant is actually a function, so we could conceivably treat those as Overall, this RFC's goal of allowing multiple enums in the same module to have variants with the same name is a reasonable thing to want, but I don't think the proposed behavior works. |
At this point I'm inclined to reintroduce the
But I think now is a good time to revisit the idea using the more structured RFC process. I know kibwen commented that this isn't a good time because of the number of breaking changes floating around, but we have open RFCs that are over 2 months old, so obviously there's no pressure to accept/reject an RFC immediately. |
The disambiguation is indeed a concern, however I do wish that explicit qualification of enum variants would work at least:
It is annoying that this fails to compile, and for now the only work-around I have found (since aliases don't work either) is just to import all variants in the scope which is really unsatisfactory. |
We believe if the compiler adhered the rules that we expect of it today, then this could be added backwards compatibly post 1.0. In particular, since today, types and module share the same namespace, it should not be legal (*) for one to actually write code that has an enum item and a mod item in the same scope, and therefore we should be able to add the new semantics proposed here backwards compatibly in the future. So, following the above reasoning, we note that this is a potentially desirable feature, but not one that we want to invest time in before 1.0. So we are closing this PR as postponed, so that we can revisit it after 1.0 is released. Footnote (*) However: The team determined during review that the above reasoning is slightly flawed, in that there is a bug in the compiler that allows one to have an enum item and a mod item in the same scope, as illustrated here: playpen This is a bug. The people present at the meeting agreed it is a bug, and we have now filed rust-lang/rust#15205 to address it.) |
An RFC to resolve enums with overlapping variant names in an elegant manner.