Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upenum variants aren't considered to be const #5873
Comments
youknowone
added a commit
to youknowone/rust
that referenced
this issue
Apr 15, 2013
youknowone
added a commit
to youknowone/rust
that referenced
this issue
Apr 15, 2013
bors
added a commit
that referenced
this issue
Apr 16, 2013
graydon
pushed a commit
to graydon/rust
that referenced
this issue
Apr 17, 2013
This comment has been minimized.
This comment has been minimized.
|
It seems like the constant checker believes that Nominating for milestone 1, welll-defined. |
This comment has been minimized.
This comment has been minimized.
|
Works now. Fixed by 877bba9 (possibly; at the very least, it includes a testcase). |
huonw
closed this
Jul 30, 2013
This comment has been minimized.
This comment has been minimized.
|
This doesn't seem to work now.
$ x86_64-apple-darwin/stage2/bin/rust run static_test.rs |
bblum
reopened this
Aug 28, 2013
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
Part of #5551; inherits its maturity milestone implicitly. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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);
} |
This comment has been minimized.
This comment has been minimized.
|
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.) |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
jaredly
commented
Mar 24, 2014
|
+1 for getting the number of variants in an enum |
thestinger
added
the
A-typesystem
label
Sep 16, 2014
This comment has been minimized.
This comment has been minimized.
|
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
|
This comment has been minimized.
This comment has been minimized.
|
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.) |
This comment has been minimized.
This comment has been minimized.
|
I think we should close this ticket. Nominating for closure. |
pnkfelix
added
I-nominated
and removed
I-nominated
labels
Feb 16, 2015
This comment has been minimized.
This comment has been minimized.
|
(closing) |
pnkfelix
closed this
Feb 19, 2015
This comment has been minimized.
This comment has been minimized.
tommit
commented
Mar 7, 2015
|
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. |
This comment has been minimized.
This comment has been minimized.
|
It's backwards compatible to add implicit const ordinals, no? Likewise for a way to get const number of variants. |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
I might be wrong on this point; I will check more carefully when I am in front of a computer again |
This comment has been minimized.
This comment has been minimized.
tommit
commented
Mar 8, 2015
|
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? |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
|
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
reopened this
Mar 8, 2015
This comment has been minimized.
This comment has been minimized.
tommit
commented
Mar 8, 2015
|
@pnkfelix Thank you for getting this thing to get sorted out and for clearing up my earlier confusion. |
This comment has been minimized.
This comment has been minimized.
|
Hmm, I tend to agree with @tommit that it should work for both explicitly assigned and unassigned values, if it works at all. |
This comment has been minimized.
This comment has been minimized.
|
(I didn't fully appreciate when commenting before that it worked only in one case and not the other.) |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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 |
rust-highfive
removed
the
I-nominated
label
Mar 12, 2015
nrc
added
the
P-medium
label
Mar 19, 2015
theemathas
referenced this issue
Mar 20, 2015
Closed
ICE: "index is not an integer-constant expression" using enum as array index. #23513
pnkfelix
referenced this issue
Mar 31, 2015
Closed
enum variants aren't considered to be const during const-evaluation #23898
This comment has been minimized.
This comment has been minimized.
|
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.) |
doy commentedApr 13, 2013
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: