-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
enum variants aren't considered to be const #5873
Comments
This will help not to meet confusing errors. In issue rust-lang#5873, the error was "expected constant expr for vector length: Can't cast str to int". It was originally "expected constant expr for vector length: Non-constant path in constant expr" (though still invalid error). This patch make the original error to be printed.
This will help not to meet confusing errors. In issue rust-lang#5873, the error was "expected constant expr for vector length: Can't cast str to int". It was originally "expected constant expr for vector length: Non-constant path in constant expr" This patch make the original error to be printed.
This will help not to meet confusing errors. In issue #5873, the error was "expected constant expr for vector length: Can't cast str to int". It was originally "expected constant expr for vector length: Non-constant path in constant expr" (though still invalid error). This patch make the original error to be printed.
This will help not to meet confusing errors. In issue rust-lang#5873, the error was "expected constant expr for vector length: Can't cast str to int". It was originally "expected constant expr for vector length: Non-constant path in constant expr" This patch make the original error to be printed.
It seems like the constant checker believes that Nominating for milestone 1, welll-defined. |
Works now. Fixed by 877bba9 (possibly; at the very least, it includes a testcase). |
This doesn't seem to work now.
$ x86_64-apple-darwin/stage2/bin/rust run static_test.rs |
I'm doubtful that the earlier testcase ever worked; 877bba9 explicitly calls out in the commit message that C style enums don't work in type signatures, only values. |
Part of #5551; inherits its maturity milestone implicitly. |
Just for the record, having integral enum constant support in type signatures is a complicated problem, since we end up needing to differentiate between types that can be checked without constant evaluation and types that require constant evaluation before they can be checked. Interleaving these two things looked exceedingly awkward when I attempted to tackle this before, hence why I punted on it. |
triage bump. The original example seems to work now: enum Category {
Bar = 4,
}
static i: int = Bar as int;
fn main () {
let x: [int, ..i] = [1, 2, 3, 4];
} This still fails, here's an updated example: enum Category {
A,
B,
C,
NumCategories,
}
static NUM_CATEGORIES: uint = NumCategories as uint;
fn main() {
let the_categories: [Category, ..NUM_CATEGORIES] = [A, B, C];
println!("{}", the_categories);
} |
I don't think the latter example (that attempts to const-eval (I do admit, it is a useful coding pattern. Though perhaps I might be able to whip up a macro that expands into the C-style enum. I will try to remember to try that tomorrow morning.) |
I consider the last case to be an anti-pattern in Rust. It creates an entry in the enum that doesn't exist and fouls up match statements. If we want to support this (which perhaps we should), we ought to add some way to get the number of variants in an enum for a constant -- but not by adding a fictitious entry to the enum. |
+1 for getting the number of variants in an enum |
Visiting for triage Updated the example to compile with the latest Rust enum Category {
A,
B,
C,
NumCategories,
}
static NUM_CATEGORIES: uint = Category::NumCategories as uint;
fn main() {
let the_categories: [Category; NUM_CATEGORIES] = [Category::A, Category::B, Category::C];
println!("{}", the_categories);
} Can confirm it still doesn't compile
|
So, just to review the situation, and repeat what @nikomatsakis and I stated earlier:
#[derive(Debug)]
enum Category {
A,
B,
C,
NumCategories,
}
const NUM_CATEGORIES: usize = Category::NumCategories as usize;
use Category::*;
fn main() {
let the_categories: [Category; NUM_CATEGORIES] = [A, B, C];
println!("{:?}", the_categories);
} This is the case where you get the following error:
Footnote 1: both @pnkfelix and @nikomatsakis think the last program above is using an anti-pattern; that is, it is not idiomatic Rust to encode meta-information like "the number of enum variants" as a member itself of the enum. (We may extend the language in the future with some sort of associated constant that provides such information, but that is not part of the current design.) Footnote 2: there is a straight-forward workaround, if one wants to insist on using the anti-pattern: Put an explicit value in for the #[derive(Debug)]
enum Category {
A,
B,
C,
NumCategories = 3,
}
const NUM_CATEGORIES: usize = Category::NumCategories as usize;
use Category::*;
fn main() {
let the_categories: [Category; NUM_CATEGORIES] = [A, B, C];
println!("{:?}", the_categories);
} Note also that the Rust compiler will catch if you put too low a value in for `NumCategories above, as long as you have not assigned "out-of-band" values to the earlier variants. In other words, this code will fail to compile: #[derive(Debug)]
enum Category {
A,
B,
C,
NumCategories = 2, // this is too low!
}
const NUM_CATEGORIES: usize = Category::NumCategories as usize;
use Category::*;
fn main() {
let the_categories: [Category; NUM_CATEGORIES] = [A, B];
println!("{:?}", the_categories);
} This yields the compile-time error:
(I suspect there may even be a straight-forward macro one could write that creates a static array of all the values, to ensure that the provided number is also not too large. Demonstrated here: http://is.gd/rGTANu Though such a macro would benefit from extensions like rust-lang/rfcs#407 for counting.) |
I think we should close this ticket. Nominating for closure. |
(closing) |
Let me get this straight. Rust doesn't allow using c-like enum variants in compile-time evaluation contexts in general, unless the user opts-in to this workaround you've pointed out. Library writers don't know which ones of their public c-like enum variants might be needed to be used as compile-time constants, so they'd have to explicitly specify the values for each variant. To me this is clearly a compiler bug, and as far as I can tell, you refuse to fix it just because the person reporting it happened to be using an anti-pattern in demonstrating it. |
It's backwards compatible to add implicit const ordinals, no? Likewise for a way to get const number of variants. |
@tommit compiler bug != language feature At one point I had a further notes here trying to further explain the above, but I think the comment thread is essentially self-explanatory, apart from one detail: I believe the phrase "C-like enum variant" is meant to refer to variants that have been given an explicit value. The example that we have been calling an anti-pattern does not use any explicit values in the variants; therefore I do not think it qualifies as a C-like enum variant. |
I might be wrong on this point; I will check more carefully when I am in front of a computer again |
The Reference claims the following:
From that quote I gather, that given the @pnkfelix You say that it's a language feature that these unassigned nullary enum variants (which belong to an enum whose all variants are nullary) aren't compile-time constants. What is the language design reasoning behind this feature? |
@tommit I was not attempting to claim that it was a language feature that these aren't compile-time constants. (I do concede that my earlier response can be interpreted that way.) I was trying to claim that changing the current language to treat them as compile-time constants would be a language feature, and thus should go through the RFC process. (After all, a ticket like this really isn't the appropriate venue to debate the value of such a change.) Here's the essence of what I was thinking when I wrote that response: I have been long under the impression that we were reserving the right to change how discriminant values are assigned by the compiler if not explicitly assigned by programmer. (Of course actually allowing such a change would probably require restricting the current language; i.e. Its quite possible that my mental model of what we were planning to permit in the future was simply over-aggressive; i.e. that no one else on the team was planning on ever changing the assignment of discriminant values, at least not for enum variants that do not have a data payload attached. |
reopening and putting on agenda for next meeting; this deserves discussion at the team meeting, if only to get clarification about what guarantees we plan with respect to discriminant value assignment. |
@pnkfelix Thank you for getting this thing to get sorted out and for clearing up my earlier confusion. |
Hmm, I tend to agree with @tommit that it should work for both explicitly assigned and unassigned values, if it works at all. |
(I didn't fully appreciate when commenting before that it worked only in one case and not the other.) |
So after discussing with @nikomatsakis i concluded that my mental model is simply wrong, and that there is not sufficient value in trying to future-proof our future discriminant value assignment. In particular @nikomatsakis pointed out to me multiple times that the chosen discriminant value need not be directly represented as the numeric value chosen; thus various tricks I was anticipating (usually revolving around ensuring that e.g. bit patterns are non-zero) should be able to be adopted in the future. Anyway, the bugs been reopened; we should fix this, for consistency's sake. |
triage: P-high (In some sense this is a feature request, or at least a request for consistently deploying a particular feature. Fixing this may be important when/if |
Decided to file a fresh issue, #23898, to ease triage. (I.e. right now the main item left on this bug is hard to actually extract from the thread of conversation as presented.) |
This compiles:
But this doesn't:
That error message doesn't seem to make sense, but that may be because it's just confused - I also get this error message in other circumstances, and I don't understand what the difference is:
The text was updated successfully, but these errors were encountered: