I have a type that has a type parameter that should, in correct usage, be only one of a subset of types. In particular, [u8; N] where N is a power of two. Since there's no way to express "must be an array of u8" as a trait bound (and much less that N is a power of two), the type parameter is unbounded. This is an internal type used only by my crate, so the lack of compile-time constraints is fine, but I would still like to debug_assert that the type is being used correctly. Is there any way that I can introspect a type parameter at runtime? What I want is basically something like this:
impl<T> Foo<T> {
fn new() -> Foo<T> {
debug_assert!(/* T is [u8; N] where N is a power of two */);
...
}
}
Given that arrays are somewhat clunky right now and support up to 32 elements only (higher than that, and you lose impls), you could simply enumerate all allowable type parameters for your type in a form of a trait.
That's a great idea, thanks! I assume this is a trait? So:
trait ValidArray {}
impl ValidArray for [u8; 1] {}
impl ValidArray for [u8; 2] {}
...
(in other words, I'm not sure what the impl ValidArray {} in your example was for)
Also, is there a way to prevent people outside the local module from just doing impl ValidArray for String {} or something like that? It doesn't really matter since this is internal code, so even w/o that guarantee, this is still great for catching accidental errors, but it'd be cool.
Then you want a "sealed" trait, which is pub but closed to additional implementations. This isn't a real concept to the compiler yet, but you can approximate it with pub-in-private tricks. Basically, you make implementations use something which is technically pub but lives in a private module, so then only those with access to that private module can really implement it. You can see this trick in rayon here.
Or just make it a pub unsafe trait, and scold anyone who implements it without upholding your specified contract.
Actually, maybe your ValidArray can just be the pub-in-private piece itself, unless you do need outsiders to be able to name it. So you'd mark it pub but write it in a private module.
(I upgraded them from debug_assert! since they're testing compile-time constants, so in release mode LLVM will remove them if they pass anyway, and if they don't will replace the function body with panic!.)