Skip to content

Instantly share code, notes, and snippets.

@Centril
Created December 4, 2017 18:55
Show Gist options
  • Save Centril/df583b162859794458b26af2e00ab6a8 to your computer and use it in GitHub Desktop.
Save Centril/df583b162859794458b26af2e00ab6a8 to your computer and use it in GitHub Desktop.
Const Trait System
//******************************************************************************
// "const_trait_system"
//******************************************************************************
/*
Dependency DAG of proposal:
[A, B] -> []
[C] -> [B] and/or [A] -- NOTE: C is moot without B or A.
[D, E] -> [B]
An arrow denotes that a proposal requires a node on the RHS to pass.
*/
//==============================================================================
// A. const fn in trait
//==============================================================================
// Removes: error[E0379]: trait fns cannot be declared const
trait Ada {
const fn compute(n: usize) -> usize;
}
// You now HAVE to write:
impl Ada for Foo {
const /* <-- mandatory */ fn compute(n: usize) -> usize {
n * 2
}
}
// This of course means that `fn compute(..)` may be used in any const context.
//==============================================================================
// B. overconstrain fn in trait impl as const
//==============================================================================
// Removes: error[E0379]: trait fns cannot be declared const
// Assume:
trait Bar {
fn baz();
fn quux() -> usize;
}
// You may now write:
impl Bar for Foo {
const fn baz() {}
const fn quux() -> usize { 1 }
}
// Foo::baz() and Foo::quux() are now usable in a const context.
//==============================================================================
// C. const impl as syntactic sugar for const fn
//==============================================================================
const impl Bar for Foo {
fn baz() {}
fn quux() -> usize { 1 }
}
// ==>
impl Bar for Foo {
const fn baz() {}
const fn quux() -> usize { 1 }
}
// constant impl means "all fns are const" semantically.
//==============================================================================
// D. allow use of trait-fn in const fn iff impl as const impl
//==============================================================================
// Consider:
trait Default { fn default() -> Self; }
// And:
impl Default for Foo {
const fn default() -> Self {
Foo(5)
}
}
impl Default for Wibble {
fn default() -> Self {
Wibble(Box::new(5))
}
}
// You may then write:
const fn example<D: Default>() -> D {
D::default()
}
// This is only callable iff the specific type for D has
// an impl of Default where default() is marked as const fn.
fn main() {
// This is allowed:
const MY_FOO: Foo = example::<Foo>();
// This is NOT:
const MY_WIBBLE: Wibble = example::<Wibble>();
}
//==============================================================================
// E. const trait bound iff impl is const impl
//==============================================================================
// Consider:
fn example<D: const Default>() -> D {
D::default()
}
// This entails that:
fn main() {
// This is allowed:
let foo = example::<Foo>();
// This is NOT:
let wibble = example::<Wibble>();
}
// The const modifier on a bound in a non-const fn means that a type can only
// be substituted for a type variable iff the impl of the required trait is
// semantically a const impl (= all fn:s are marked as const).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment