Expand description
wishcasting /ˈwɪʃˌkɑːstɪŋ/
n. — The act of interpreting information or a situation in a way that casts it as favorable or desired, although there is no evidence for such a conclusion; a wishful forecast.
§pattern-wishcast
proc macro implementing some parts of pattern types, a proposed rust language feature which may be added soon™
pattern types are a form of predicate subtyping - they create subtypes of existing types based on match
-like predicates. examples from the RFC:
// Proposed future syntax
Option<i32> is Some(_) // only the Some variant
i32 is 1..16 // integers from 1 to 15
&[Ordering] is [Ordering::Less, ..] // slices starting with Less
pattern types would replace types like NonZero<u32>
with the more general u32 is 1..
, enabling niche optimizations where Option<u32 is 1..10>
is the same size as u32
.
here’s to hoping that demonstrating the usefulness of predicate subtyping for enum variants with this limited hack speeds the addition of real pattern types
rust has an unstable implementation that works for numeric ranges but not enum variants or subtyping yet.
§what
compile-time subtyping relationships between enums with conditionally uninhabited variants. hopefully probably maybe safe transmute-based conversions.
pattern_wishcast::pattern_wishcast! {
enum StuckEvaluation = {
BoundVar(String)
};
enum Value is <P: PatternFields> = StuckEvaluation | {
Number { value: i32 },
Boolean { value: bool },
// Vec<Self> applies the pattern recursively!
// CompleteValue tuples contain only CompleteValue elements
Tuple { elements: Vec<Self> },
};
// Complete values: no stuck states anywhere in the tree
type CompleteValue = Value is Number { .. } | Boolean { .. } | Tuple { .. };
// with real pattern types we wouldn't need explicit wildcards
type PartialValue = Value is _;
#[derive(SubtypingRelation(upcast=to_partial, downcast=try_to_complete))]
impl CompleteValue : PartialValue;
}
generates transmute-based upcasts and runtime-checked downcasts. auto-generated safety tests.
§what this achieves
pattern-wishcast
lets you pretend you have pattern types for enum variants in stable rust by:
- generating traits with associated types that are either
Never
or()
to make variants conditionally uninhabited - generating upcast and downcast methods with ref/mut ref variants where safe
- recursive patterns: applying patterns recursively with
Self
- something the current pattern types proposal doesn’t support. in the example above, aCompleteValue::Tuple
guarantees ALL nested elements are also complete, not partially evaluated.
§safety
transmutes between types differing only in unused uninhabited variants seem to work under miri, but i’m not confident about soundness. if you find safety issues please report them.
§safety note: no mutable reference upcasting
when you use #[derive(SubtypingRelation(upcast=foo, downcast=bar))]
, the macro generates:
foo(self) -> SuperType
- upcast owned valuefoo_ref(&self) -> &SuperType
- upcast immutable referencebar(self) -> Result<SubType, Self>
- checked downcast owned valuebar_ref(&self) -> Result<&SubType, ()>
- checked downcast immutable referencebar_mut(&mut self) -> Result<&mut SubType, ()>
- checked downcast mutable reference
why no mutable reference upcasting? upcasting &mut SubType
to &mut SuperType
would allow:
- writing a
SuperType
-only variant through the upcast reference - violating
SubType
’s invariant that certain variants are uninhabited - undefined behavior when the value is used as
SubType
again
§limitations
- only patterns that make entire variants conditional work. can’t restrict a field to a range like real rust patterns
- downcast gen has builtin support for only
Vec<T>
,Box<T>
,Option<T>
for generic containers containing Value types- requires
#[unsafe_transmute_check(iter = ".values()")]
for custom containers, don’t mess up or you’ll transmute never types into existence
- requires
§examples
see examples/expression_evaluator.rs
for stuck evaluation -> resolved evaluation demo using CompleteValue
and PartialValue
§status
works but hacky. would be much cleaner with native pattern types support in rustc.
pre-release for now, expect the API to change. might be small changes, might get reworked. have only been iterating on this for a few days.
rust version compatibility: works on stable rust! uses an internal Never
type instead of requiring nightly. for nightly users, the never_type
feature enables the real !
type.
Macros§
Enums§
- Never
- An uninhabited type for use in pattern-wishcast generated code.