{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreifdy6veragd74fiyyatazderajkr34alm7kuidphpvvurbifpw5s4",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3mg7hkpfhso32"
},
"path": "/t/f-pattern-types-subsets-enums-using-as/24048#post_17",
"publishedAt": "2026-03-03T19:23:53.000Z",
"site": "https://internals.rust-lang.org",
"tags": [
"[1]",
"1], I believe it's sugar that would make \"newtype variants\" nicer to work with[[2]",
"[3]",
"↩︎"
],
"textContent": "FWIW, the example as currently spelled in the OP\n\nDidingasLushis:\n\n>\n> #[derive(Debug, Error)]\n> pub enum MyError {\n> #[error(\"not found\")]\n> NotFound,\n>\n> #[error(\"invalid state\")]\n> InvalidState,\n>\n> #[error(\"permission denied\")]\n> PermissionDenied,\n> }\n>\n> #[derive(Debug, Error)]\n> pub enum MyErrorSubset {\n> MyError::NotFound,\n> MyError::PermissionDenied,\n> }\n>\n\nseems like it's a combination of \"enum variants are types\" and \"types as enum variants.\" The \"pattern restricted subtype\" spelling\n\nscottmcm:\n\n>\n> type MyErrorSubset = MyError is (MyError::NotFound | MyError::PermissionDenied);\n>\n\nfeels to me like it would be the most commonly used option in a world with all options available, as it asks for the simple type restriction of `MyError` to the possible variants without any layout changes (thus true no-op conversion to `MyError`) and inheriting all (immutable) trait functionality automatically.\n\nWith pattern restricted subtypes, the \"enum variant as type\" `MyError::NotFound` would likely be spelled `MyError is MyError::NotFound`. But \"types as enum variants\" still gives the tuple struct equivalent for enum types where the variants are indexed instead of named, and while this is _technically_ just sugar1], I believe it's sugar that would make \"newtype variants\" nicer to work with[[2].\n\n* * *\n\nIn any case, pattern restricted types are stalled because they're _difficult_. We want to inherit all functionality from `MyError` to `MyErrorSubset`, but while `&MyErrorSubset ⊆ &MyError`, `&mut MyError ⊆ &mut MyErrorSubSet`, and also `&MyError ⊆ &mut MyError` and `&MyErrorSubset ⊆ &mut MyErrorSubset`, so it's a complicated mess, and internal mutability makes things even more complicated… knowing what associated functions and trait impls can be provided on the subset type is a very thorny problem, and it gets even _more_ thorny once you start considering forwards compatibility with API evolution that we deem semver compatible.\n\nBut even given all of that, pattern restricted types _are_ super useful, and I hope I get to see Rust gain a version of them within my career, even if it's massively restricted[3].\n\n* * *\n\n 1. Whether it's just sugar or not depends on whether the type has sum type semantics (multiple variants using the same type are distinct) or union type semantics (multiple variants using the same type are unified). In the face of generics, I believe that sum type semantics are the consistent choice. ↩︎\n\n 2. In short, `enum EnumType { use VariantType }` would be sugar for `enum EnumType { 0(VariantType) }`, which we'd likely write today as `enum EnumType { Variant(VariantEnum) }`. Pattern matching would use the index or, in the most ideal case, allow using type ascription syntax when that is unambiguous. ↩︎\n\n 3. A version which only allows pattern restricted types for the field of newtype structs and requires `unsafe` for accesses to the inner field (thus manual and unsafe forwarding of any traits) simply as a way to spell custom niches in user code would be wonderful, even without further niceties that it could theoretically enable. ↩︎\n\n\n",
"title": "F-pattern_types : Subsets enums using as"
}