You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Const generic ICE: constant in type had an ignored error: TooGeneric #66962
Just for the sake of maybe helping to drill down on the cause of the bug by way of comparison, here's an example of similar code that's somewhat more complex but that interestingly does work fine:
#![allow(incomplete_features)]#![feature(const_fn)]#![feature(const_generics)]#![feature(const_if_match)]use std::fmt::{self,Debug,Formatter};structCFG<constOPT_A:char,constOPT_B:bool>{}impl<constOPT_A:char,constOPT_B:bool>CFG<OPT_A,OPT_B>{constLEN:usize = matchOPT_A{'A' => 64,'B' => 128,'C' => 256,'D' => 512,
_ => 512,};constIS_TRUE:bool = OPT_B;}structCFGBuilder<constA:char,constB:bool>{}typeOptions = (usize,bool);impl<constA:char,constB:bool>CFGBuilder<A,B>{constRESULT:Options = (CFG::<A,B>::LEN,CFG::<A,B>::IS_TRUE);}constDEFAULT_CFG:Options = CFGBuilder::<'A',true>::RESULT;constALT_CFG:Options = CFGBuilder::<'B',false>::RESULT;structB1{arr:[u8;DEFAULT_CFG.0],}implB1{constCAP:usize = DEFAULT_CFG.0;constIS_TRUE:bool = DEFAULT_CFG.1;constfnnew(val:u8) -> Self{Self{arr:[val;Self::CAP],}}}implDebugforB1{fnfmt(&self,f:&mutFormatter) -> fmt::Result{write!(f,"B1 IS_TRUE: {}\n{:?}",Self::IS_TRUE,unsafe{// Not actually unsafe, because it can't go out of bounds.self.arr.get_unchecked(..)})}}structB2{arr:[u8;ALT_CFG.0],}implB2{constCAP:usize = ALT_CFG.0;constIS_TRUE:bool = ALT_CFG.1;constfnnew(val:u8) -> Self{Self{arr:[val;Self::CAP],}}}implDebugforB2{fnfmt(&self,f:&mutFormatter) -> fmt::Result{write!(f,"B2 IS_TRUE: {}\n{:?}",Self::IS_TRUE,unsafe{// Not actually unsafe, because it can't go out of bounds.self.arr.get_unchecked(..)})}}constONE:B1 = B1::new(1);constTWO:B2 = B2::new(2);fnmain(){println!("{:?}",ONE);println!("{:?}",TWO);}
The backtrace is not too useful as it shows the reporting code rather than the code that raised the error. I did a little bit of debugging and I think rustc_mir::interpret::operand raises the error in this code:
Adding some debug prints, I see that the ParamConst is something like ParamConst { index: 0, name: "CFG" }. Is there a way to resolve this "CFG" to the actual const Config struct so that I can select the field?
TooGeneric shouldn't really cause an error, it should be silent and simply leave the constant unevaluated (until a later situation in which the const parameter is replaced with an actual value).
This is a legitimate error, but it shouldn't have been ICEing. I'm sorry I didn't notice it earlier!
The reason the original example shouldn't compile is because it can cause post-monomorphization const-eval failures!
The struct should have a bound which effectively forces all use sites to evaluate the constant and ensure it has no errors (but this is not yet implemented - the syntax where [u8; {CFG.arr_size}]:, should do this).
Note that the where bound doesn't need to use u8 as the element type, as long as it passes the same Config parameter as the actual use in a field type.
This might require coordination with @rust-lang/wg-traits to make sure the WF semantics here are coherent with the rest of WF.
Thanks for showing a way forward @eddyb
The previous pull request did in fact not resolve the issue for me.
So we need to construct a wrapper around the arr_size? i don't quite understand why/what that does. Is there somewhere to read up on it? just to avoid cargo culting.
we have a bit of a messaging issue (cc @varkor@yodaldevoid), you never have to write braces around the array length expression, [T; N] works just as well (the braces aren't for const generic params specifically, they're for expressions in paths, e.g. Foo<T, {N+M}>)
[T; N] (or [T; {N}], same thing) and Foo<T, {N}>, where N is a const generic parameter name, will not rely on a const expression, but let the typesystem see that a const parameter is used there, so CfgArray in your example isn't useful
OTOH, an expression like N+1 or CFG.arr_size is currently treated opaquely (because we have no algorithm to unify two such expressions), so if you write it twice, the compiler doesn't know it's the same one, hence using a type alias to write it only once
I've opened an issue about the first observation (#68387), but there are definitely going to be learnability problems with the latter two until we address it properly.
@eddyb
so its kinda like my workaround example?
the rules around when you need to be using brackets are kinda... inconsistent, but thats probably a different issue all together.
Activity
Centril commentedon Dec 3, 2019
Reproduces without the feature gate enabled.
hellow554 commentedon Dec 3, 2019
It is noteworthy (and probably a bug too), that it only works if you use
#[derive(PartialEq, Eq)].My code below does ICE on stable, but not on nightly, but emits an error:
Backtrace:
slightlyoutofphase commentedon Dec 3, 2019
Just for the sake of maybe helping to drill down on the cause of the bug by way of comparison, here's an example of similar code that's somewhat more complex but that interestingly does work fine:
osa1 commentedon Dec 4, 2019
The backtrace is not too useful as it shows the reporting code rather than the code that raised the error. I did a little bit of debugging and I think
rustc_mir::interpret::operandraises the error in this code:osa1 commentedon Dec 4, 2019
Adding some debug prints, I see that the
ParamConstis something likeParamConst { index: 0, name: "CFG" }. Is there a way to resolve this "CFG" to the actual constConfigstruct so that I can select the field?eddyb commentedon Dec 19, 2019
TooGenericshouldn't really cause an error, it should be silent and simply leave the constant unevaluated (until a later situation in which the const parameter is replaced with an actual value).4 remaining items
eddyb commentedon Jan 18, 2020
This is a legitimate error, but it shouldn't have been ICEing. I'm sorry I didn't notice it earlier!
The reason the original example shouldn't compile is because it can cause post-monomorphization const-eval failures!
The
structshould have a bound which effectively forces all use sites to evaluate the constant and ensure it has no errors (but this is not yet implemented - the syntaxwhere [u8; {CFG.arr_size}]:,should do this).eddyb commentedon Jan 18, 2020
Given the lack of const expression unification, this is what it would take:
Note that the
wherebound doesn't need to useu8as the element type, as long as it passes the sameConfigparameter as the actual use in a field type.This might require coordination with @rust-lang/wg-traits to make sure the WF semantics here are coherent with the rest of WF.
djugei commentedon Jan 20, 2020
Thanks for showing a way forward @eddyb
The previous pull request did in fact not resolve the issue for me.
So we need to construct a wrapper around the arr_size? i don't quite understand why/what that does. Is there somewhere to read up on it? just to avoid cargo culting.
specifically whats the difference to
and what does the "empty" where clause do.
eddyb commentedon Jan 20, 2020
@djugei So there's a few things going on:
[T; N]works just as well (the braces aren't for const generic params specifically, they're for expressions in paths, e.g.Foo<T, {N+M}>)[T; N](or[T; {N}], same thing) andFoo<T, {N}>, whereNis a const generic parameter name, will not rely on a const expression, but let the typesystem see that a const parameter is used there, soCfgArrayin your example isn't usefulN+1orCFG.arr_sizeis currently treated opaquely (because we have no algorithm to unify two such expressions), so if you write it twice, the compiler doesn't know it's the same one, hence using a type alias to write it only oncevarkor commentedon Jan 20, 2020
I've opened an issue about the first observation (#68387), but there are definitely going to be learnability problems with the latter two until we address it properly.
varkor commentedon Jan 20, 2020
This issue should be addressed in #68388 (though the code in the original post will not be accepted).
djugei commentedon Jan 20, 2020
@eddyb
so its kinda like my workaround example?
the rules around when you need to be using brackets are kinda... inconsistent, but thats probably a different issue all together.
varkor commentedon Jan 20, 2020
Yes, this is #68257. These examples should all work (and hopefully will do soon!).
Rollup merge of rust-lang#68388 - varkor:toogeneric-wf, r=eddyb
Rollup merge of rust-lang#68388 - varkor:toogeneric-wf, r=eddyb
Rollup merge of rust-lang#68388 - varkor:toogeneric-wf, r=eddyb
Rollup merge of rust-lang#68388 - varkor:toogeneric-wf, r=eddyb