-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
What are our options?
- we teach name resolution (
rustc_resolve) to hideenumgeneric parameters from the discriminant expression- this effectively enshrines that we don't want the parameterization to happen
- I'm not sure this can be backwards-compatible with 2.
- we keep the current name resolution support but error if we can't evaluate to concrete values
- the concrete values are necessary to check, at the definition site, that discriminants don't overlap
- there are special-cases (only the first variant having an explicit discriminant, while the rest keep counting up) where we could check w/o knowing the values
- long-term we could let more examples compile via explicit
!=bounds
- note that expressions that use generics can still evaluate to concrete values
- we could make this work w/o
# by using the same approach as in typeck: always expose repeat countAnonConsts' parent ingenerics_of. #70452, asenums are in a similar situation that shouldn't cause query cycles - EDIT: opened typeck: always expose explicit enum discriminant
AnonConsts' parent ingenerics_of. #70825 for this
- the concrete values are necessary to check, at the definition site, that discriminants don't overlap
Examples of current behavior:
Note: #![feature(const_generics)] is used below so that this special-case kicks in:
rust/src/librustc_typeck/collect.rs
Lines 1183 to 1185 in 62c6006
| // FIXME(#43408) enable this always when we get lazy normalization. | |
| Node::AnonConst(_) => { | |
| // HACK(eddyb) this provides the correct generics when |
Also, note that the reason for the uniform current treatment (which doesn't consider enum parameters as not in scope of discriminants), is because rustc_resolve treats surrounding generics as being in scope of AnonConsts, always - all the bugs later in compilation are due to the lack of lazy normalization (see #43408).
This ICEs currently (playground):
#![feature(const_generics)]
#[repr(usize)]
enum Foo<T> {
Zero = 0,
SizeOf = std::mem::size_of::<T>(),
}with
error: internal compiler error: src/librustc/ty/mod.rs:2538: enum discriminant depends on generic arguments
--> src/lib.rs:6:14
|
6 | SizeOf = std::mem::size_of::<T>(),
| ^^^^^^^^^^^^^^^^^^^^^^^^
Same thing happens if a const parameter is used instead of size_of::<T>().
If we choose option 2, this ICE will turn into a regular error.
EDIT: and this currently compiles on nightly (playground):
#![feature(const_generics, arbitrary_enum_discriminant)]
#[repr(usize)]
enum MyWeirdOption<T> {
None = 0,
Some(T) = std::mem::size_of::<*mut T>(),
}And using *mut *mut T instead of *mut T would make it work even when T: Sized isn't known.
(If not for the substitution failure, you could remove #![feature(const_generics)])
cc @rust-lang/compiler @rust-lang/lang