Closed HadrienG2 closed 2 years ago
Note that impl exhaustiveness checking could also enable the following:
struct Bool<const B: bool>;
impl Bool<{true }> { const B: bool = true; }
impl Bool<{false}> { const B: bool = false; }
fn should_work<const B: bool>() -> bool {
Bool::<{B}>::B
}
But whether it should is obviously a different question.
This is really a feature request, and deserves its own RFC. However, implementation doesn't seem implausible, as we already have exhaustiveness checking in other locations, so we could reuse that mechanism.
@varkor Agreed, figured out as much while trying to reduce the case further and discovering that contrary to what I thought, this cannot be merely implemented as evaluating Bool<B>
to either Bool<true>
or Bool<false>
once B
is known, because in Rust the compiler must prove that use of Bool<B>
is correct for all values of B
.
The error message now is:
error[E0391]: cycle detected when const-evaluating + checking `ConstLenIterator::Next::{{constant}}#0`
--> src/lib.rs:15:33
|
15 | type Next: ConstLenIterator<{LEN.saturating_sub(1)}, Item = Self::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `ConstLenIterator::Next::{{constant}}#0`...
--> src/lib.rs:15:33
|
15 | type Next: ConstLenIterator<{LEN.saturating_sub(1)}, Item = Self::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating `ConstLenIterator::Next::{{constant}}#0`...
--> src/lib.rs:15:33
|
15 | type Next: ConstLenIterator<{LEN.saturating_sub(1)}, Item = Self::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `ConstLenIterator::Next::{{constant}}#0`...
--> src/lib.rs:15:33
|
15 | type Next: ConstLenIterator<{LEN.saturating_sub(1)}, Item = Self::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `ConstLenIterator::Next::{{constant}}#0`...
--> src/lib.rs:15:33
|
15 | type Next: ConstLenIterator<{LEN.saturating_sub(1)}, Item = Self::Item>;
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires const-evaluating + checking `ConstLenIterator::Next::{{constant}}#0`, completing the cycle
note: cycle used when processing `ConstLenIterator`
--> src/lib.rs:13:1
|
13 | trait ConstLenIterator<const LEN: usize> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
In the same vein, the following does not work but "should":
trait Tr<const B: bool> {}
struct Ty;
impl Tr<true> for Ty {}
impl Tr<false> for Ty {}
struct Test<const B: bool, T: Tr<B>>(T);
struct Test2<const B: bool>(Test<B, Ty>);
Rust is unable to infer that Ty: Tr<B>
for all B
.
this is mostly tracked by https://github.com/rust-lang/project-const-generics/issues/26 and can also achieved by using specialization (by adding an impl which covers the whole type).
Adding if
to the type level is something I've also previously thought before, but probably isn't something we should add for Rust rn and would definitely require a lang mcp or rfc.
closing this issue
So, as part of a mad science experiment, I am trying to define the following trait in Rust:
Now, Rust would clearly need new language features such as type-level
if
andimpl Trait
in traitfn
s for this pseudocode to actually work as-is. But as discussed in this internals thread, it seems that const generics could enable a decent library-based approximation of the desired behavior:Unfortunately, this does not compile:
I have managed to reduce it to the following, admittedly silly, test case...
...which fails with...
It seems to me that this could be resolved by introducing some kind of impl exhaustiveness checking so that the compiler can prove that the
Identity
trait is implemented for all variants of Bool.