reify-reflect-core 0.1.0

Core Reflect/Reify traits and RuntimeValue types
Documentation
  • Coverage
  • 100%
    12 out of 12 items documented6 out of 7 items with examples
  • Size
  • Source code size: 11.9 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.85 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 42s Average build duration of successful builds.
  • all releases: 1m 9s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • joshburgess/reify-reflect
    1 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • joshburgess

reflect-core

Core trait definitions for type-level reification and reflection.

This crate provides the foundational [Reflect] trait, the [reify] function, and the [RuntimeValue] enum.

The Reification/Reflection Pattern

This implements the pattern from Kiselyov & Shan's "Functional Pearl: Implicit Configurations" (popularized by Kmett's Haskell reflection library), adapted to Rust with branded lifetimes for scoping safety.

  • [Reflect]: Type-level value → runtime value. A type that encodes a value at the type level can produce it at runtime.

  • [reify]: Runtime value → scoped type-level context. Takes a runtime value and passes it to a continuation as a branded [Reified] token. The branded lifetime prevents the token from escaping the callback.

Haskell comparison

In Haskell:

reify :: a -> (forall s. Reifies s a => Proxy s -> r) -> r
reflect :: Reifies s a => proxy s -> a

In Rust, the forall s is modeled by an invariant lifetime 'brand on [Reified]. The higher-rank bound for<'brand> on the callback ensures the token cannot escape, just as Haskell's rank-2 type prevents s from escaping.

Unlike Haskell's reflection library (which uses unsafeCoerce to fabricate typeclass dictionaries from GHC internals), this implementation is safe all the way down: no unsafe code, no compiler-internal assumptions, scoping enforced mechanically by the borrow checker.

Examples

use reify_reflect_core::reify;

// Lift a runtime value into a scoped type-level context
let result = reify(&42i32, |token| {
    let val: &i32 = token.reflect();
    *val + 1
});
assert_eq!(result, 43);