Crates.io | pattern-wishcast |
lib.rs | pattern-wishcast |
version | 0.0.1-pre.3 |
created_at | 2025-07-05 03:56:24.400178+00 |
updated_at | 2025-07-07 03:36:30.423976+00 |
description | Pattern types emulation for conditional variants using conditional never types |
homepage | |
repository | https://github.com/LunNova/x |
max_upload_size | |
id | 1738731 |
size | 67,779 |
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.
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.
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.
pattern-wishcast
lets you pretend you have pattern types for enum variants in stable rust by:
Never
or ()
to make variants conditionally uninhabitedSelf
- something the current pattern types proposal doesn't support. in the example above, a CompleteValue::Tuple
guarantees ALL nested elements are also complete, not partially evaluated.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.
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 referencewhy no mutable reference upcasting? upcasting &mut SubType
to &mut SuperType
would allow:
SuperType
-only variant through the upcast referenceSubType
's invariant that certain variants are uninhabitedSubType
againVec<T>
, Box<T>
, Option<T>
for generic containers containing Value types
#[unsafe_transmute_check(iter = ".values()")]
for custom containers, don't mess up or you'll transmute never types into existencesee examples/expression_evaluator.rs
for stuck evaluation -> resolved evaluation demo using CompleteValue
and PartialValue
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.