Code change:
ing a value of an empty enum is valid, however ing a reference to a value of an empty enum produces . I tried this code (): I expected to see this happen: The code should compile with no issue, and the function should never actually execute because has no variants and thus cannot be instantiated. Instead, this happened: The bug exists on 1.47.0 and 1.49.0-nightly (2020-10-18 ) running on the playground. I first found this bug on 1.46.0. : <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
This is currently working as intended, but maybe we should say so in the diagnostic
Why is this the intended behavior? I find it notably surprising because I can usually replace with , and the commiler takes care to insert (de)references magically. This would be an exception.
I don't recall, but you might be able to find some of the old discussions
I was just reading some discussion on the exhaustive_patterns issue: IIUC, the reason that (where is an uninhabited type) is considered inhabited is because unsafe code can construct an -reference to an uninhabited type (e.g. with or ). I don't know enough to be sure though.
Though unsafe code can also construct an uninhabited without using references; e.g.: () Output: Errors: So maybe what I said in is not correct?
I think the difference is that creating a value of type like you did is Undefined Behavior, but creating a isn't. Try running your code using the MIRI tool (available on the playground under Tools), it usually tells you when you do UB
Indeed, transmuting to didn't make Miri report UB (though attempting to print the value did) but transmuting to did.
Nice. Indeed dereferencing a reference to unintialized memory is also UB. Instructions to fix this: add a test case named after this issue in the folder find where the error message is emitted (somewhere in ) check when the type is and the subtype is uninhabited (which you can test using ) in the above case, add a note to the error message, saying something like "references are always considered inhabited". I'm not sure if we want to mention why. maybe add some related positive and negative tests to make sure we only emit the new note when relevant maybe test and handle cases like as well? modify labels: +E-easy +E-mentor
On the contrary, constructing a which does not reference a valid is instant UB . A value of type is just as invalid as a value of type .
Oh shoot, I understood the opposite. Then I've misunderstood what says in their blog post: Maybe that post is old and things have changed since? Or maybe unintialized memory does not count as an invalid value?
The rules for validity of reference are not finally decided yet, but still being discussed at rust-lang/unsafe-code-guidelines. To not preempt the conclusion of this discussion, the docs declare as much UB as is possible -- we can always relax UB later, but introducing more UB is a breaking change.
Ok, I understand that if we want to have the option to relax this later, then we can't have the compiler rely on it. So we must treat as inhabited. Otherwise we would accept the following but it would become unsound if we relax the UB: So should stay as it currently is and my are still the way to go.
claim
Thanks for taking this on ! Feel free to ask me questions here or on .
Thanks for the warm welcome :) I do have questions, but I already made a preliminary commit to check if I'm going in the right direction: (edited because I missed a file) Is that ok, or is it better if I ask questions before committing, or just make a PR and adapt it?
That commit looks like what we want yes :) Go ahead and make a PR, it's easier to comment on specific bits of the code
For those who (like me) find this after googling "references are always considered inhabited" (the compiler's help message), the current discussion on this topic is happening in
I've a comment here: Which suggests that we consider making it UB to construct such a reference, so that this macro code doesn't confusingly start breaking for empty enums:

Related discussion:
text: <ins> enum A {} //~^ NOTE `A` defined here fn f(a: &A) { match a {} //~^ ERROR non-exhaustive patterns: type `&A` is non-empty //~| NOTE the matched value is of type `&A` //~| NOTE references are always considered inhabited } fn main() {} </ins>