#![feature(const_generics)]
use std::mem::size_of;
struct MaybeBox <T : Sized> {
inline: [ T ; (size_of::<T>() <= size_of::<Box<T>>()) as usize],
boxed: [Box<T>; (size_of::<T>() > size_of::<Box<T>>()) as usize],
}
(Please ignore the implications on alignment, that is a separate issue.)
This currently fails with error: constant expression depends on a generic parameter; note: this may fail depending on what value the parameter takes.
Is this intended to eventually work? If so, what's currently holding it back from working? If not, what prevents this from working? Is there a way to work around it? Should we provide a way to do this? (Imho, yes.)
Thankfully there is a workaround, type aliases to the rescue! playground
oh Rust, why does the more complex case work over the simple case?
edit: after a bit more testing, you can't actually use this type. It runs into an ICE. I think that const-generics just can't handle general expressions just yet. This makes sense, since we only got usable const-generics a little while ago, so general expressions are probably still in the pipeline.
To work around this, you have to use SmallBoxInner directly, and supply the correct size. You can sprinkle asserts around to check the size at the beginning of every function on SmallBoxInner.
This is a bit unfortunate, but that's how it is right now. That kinda kills the usecase of a generic type that can be seemlessly used as either a value unless it is too big, in which case it is boxed.
I guess you could just use the following type for that
I have every expectation that something like this will eventually be possible, but bounding on expressions like that is not coming super-soon, AFAIK, as it starts to hit expression equivalence questions that were explicitly out-of-scoped before.
Let's get the basics reliable and stabilized first. You can always do MaybeBox with unsafe for now.
pub struct Layout<T>(T);
trait Pick<const Bool: bool> {
type Choice;
}
impl<T> Pick<true> for Layout<T> {
type Choice = T;
}
impl<T> Pick<false> for Layout<T> {
type Choice = Box<T>;
}
This runs into the bounds problems for const-generics, you may be able to use specialization to get around this
pub struct Layout<T>(T);
trait Pick<const Bool: bool> {
type Choice;
}
impl<T, const Bool: bool> Pick<Bool> for Layout<T> {
default type Choice = Box<T>;
}
impl<T> Pick<true> for Layout<T> {
type Choice = T;
}
This way if we fail to unify with true for whatever reason, we can fall back on the general case. Although this logic may be faulty, as the interaction between const generics and specialization aren't well specified.