Pattern Types Design Doc
Pattern types are the general idea of having a type T is p
(e.g. u32 is 0..10
), that indicates a value of type T
that matches pattern p
.
I want this document to gather all the constraints and possibilities we've uncovered around this idea.
Design Goals (opinionated)
- Should not break any existing code.
- Pattern inference should not influence runtime behavior (like UB).
- The same function should not need to be monomorphised multiple times for different patterns. This could be allowed as an optimization, e.g. when inlining integer division.
- Small changes to the code should not suddenly require more or fewer match arms.
- Small changes to type inference also shouldn't do that.
- Which arms a
match
has should not influence type inference of its scrutinee.
Code examples and design constraints
I've gathered here code we'd more or less like to write. Some of these examples are pretty core to the idea of pattern types, others will need to change in the final design.
This section does not discuss solutions, only constraints and desires.
Sources for this document:
Basic Idea
Representation
Exhaustiveness
Subtyping
Inference
Const generics
Traits and methods
Any
There's a backwards-compatilibity subtlety around Any
:
API Migration
We'd like to be able to migrate an API to a more precise one without breaking downstream crates.
- trait+subtyping madness
fn(T as p)
? what about its TypeId
?
Open Design Questions
- how precise subtyping
- performance: this will require a lot of pattern checking. E.g. to prove that
None|Some(_)
is the same as _
is the same as exhaustiveness-checking (NP-complete). That said, we'd likely only have small patterns around.
- Do we want an easy mechanism to insert runtime panic to satisfy the pattern type?
.try_into().unwrap()
would be nice (but requires advanced trait features).
Proposed Solutions
- Mostly: see the pre-RFC
- For backcompat, crates opt-in to pattern types. Each function defines two functions: one with the pattern type, the other with the base type and a runtime panic. Crates see one or the other (at resolution time) depending on their opt-in. Opt-in crates can do the runtime check by hand with
.try_into().unwrap()
if they want.