rfc-proposal
This is roughly what is described in the RFC.
TL;DR
- Traits can be declared as
const, in which case all methods are "maybe-const" (depending on the impl) - Impl can decide whether it is implementing
const Trait(const or maybe-const methods)
Design axioms
- The step from a monomorphic
const fnto one with a generic bound should be minimal- In this proposal, you just add
T: ~const Default, which is easy to suggest via compiler error.
- In this proposal, you just add
- Most traits want to be "all or nothing" (all fns const or no fns const).
- Therefore you write
const trait Default { fn default() }with no indication onfn default.
- Therefore you write
- Adding
constto an item should not be a breaking change- In this proposal we extend this rule to include changing to
const trait Fooandimpl const Foo.
- In this proposal we extend this rule to include changing to
Default trait and impl
Equivalent of default trait and impl:
#![allow(unused)] fn main() { const trait Default { fn default() -> Self; } struct Wrapper<T> { value: T } impl<T> const Default for Wrapper<T> where T: ~const Default, { 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(), Some(v) => v, } } }
Potential user confusion
If I write this...
#![allow(unused)] fn main() { const fn foo() {} }
I have a function that can be used in or out of a const block. But if I put that const keyword on a generic bound...
#![allow(unused)] fn main() { const fn foo<T: const Default>() { } }
...I have a function that requires a const impl, which can be surprising (although it makes sense when you think about it, since trait bounds are declaring things that can be used by foo, not things that it does). However, it is backwards compatible to remove the const here. (It's not backwards compatible to add it.)