(const)
everywhere
TL;DR
- Write
const
to mean "can only do const things" - Write
(const)
to mean "can only directly do const things, but may do non-const things via trait bounds"
Design axioms
- We will want a lower floor than
const
eventually- What we've learned from the
?Sized
experience is that it's best to have people "ask for the things they need".
- What we've learned from the
- You should be able to declare a maybe-const function without understanding effects.
- Therefore, we prefer a
const
-keyword-based syntax.
- Therefore, we prefer a
Default trait and impl
Equivalent of default trait and impl:
#![allow(unused)] fn main() { (const) trait Default { (const) fn default() -> Self; } struct Wrapper<T> { value: T } impl<T> Default for Wrapper<T> where T: (const) Default, { (const) fn default() -> Self { Wrapper { value: T::default() } } } (const) fn get_me<T>(x: Option<Wrapper<T>>) -> Wrapper<T> where T: (const) Default, { match x { None => <Wrapper<T>>::default(), // <-- do we need something here? Some(v) => v, } } }
Variations
I'm not persuaded by putting the (const)
before the keyword trait
:
#![allow(unused)] fn main() { (const) trait Default { (const) fn default() -> Self; } }
It seems inconsistent with how the impl
works (impl (const) Default
) and how bounds work ()T: const Default
). I would therefore expect the following:
#![allow(unused)] fn main() { trait (const) Default { (const) fn default() -> Self; } }
Question though, what does it mean to write (const)
anyway? It indicates the "floor" for default functions? But that is indicated on a per-function basis.
Another option is to just say that the trait is "generic over const" if it has methods that are; that has a downside in that it rules out the ability to have a trait that has "just" a (const) fn
method:
#![allow(unused)] fn main() { trait Default { (const) fn foo<T: (const) Debug>() -> Self; } }
All of this makes me wonder if we can come up with a syntax for more explicitly "tying" things together, but I'm not sure what it would be. For example (trait)
or (fn)
or even const(if trait)
...? Or T: (fn) Debug
, which would mean "add this to the effects of the function"...?