Opaque Types
A pub opaque type is a sum type whose constructors, fields, and variant
patterns are private to its defining module. Outside that module the type is
visible and can be used in annotations, as function parameters, and as return
types, but callers cannot inspect or construct its internal representation
directly.
// in module user_ids.vtxpub opaque type UserId { UserId(value: String) }
// Smart constructor. The only public way to create a UserId.pub fn make(s: String): UserId { UserId(value: s) }
// Public accessor. Exposes the value without leaking the constructor.pub fn unwrap(uid: UserId): String { match uid { UserId(value: v) => v, }}What is restricted outside the defining module
Section titled “What is restricted outside the defining module”| Operation | Error |
|---|---|
UserId(value: "x"). Variant constructor call | E127 |
uid.value. Field access | E128 |
match uid { UserId(value: v) => v }. Variant pattern | E129 |
| Record update syntax on the opaque type | E130 |
What is allowed outside the defining module
Section titled “What is allowed outside the defining module”- Using the type in annotations:
fn foo(uid: UserId): UserId - Passing values through:
fn passThrough(uid: UserId): UserId { uid } - Wildcard match:
match uid { _ => 0 } - Calling the module’s public smart constructors and accessors
// in module consumer.vtximport user_ids.{UserId, make, unwrap}
fn run(): String { let uid = make("abc") // OK. Uses the smart constructor unwrap(uid) // OK. Uses the public accessor}
fn bad(): UserId { UserId(value: "x") } // E127fn bad2(uid: UserId): String { uid.value } // E128Exhaustiveness
Section titled “Exhaustiveness”Because variant internals are hidden, match on an opaque type from outside
its defining module requires a wildcard arm (_ => ...). Any variant
pattern arm will be rejected with E129, and a match with no wildcard and no
valid arms is non-exhaustive (E105).
// OK. Wildcard covers the opaque typematch uid { _ => "some value",}Syntax
Section titled “Syntax”opaque is only valid in combination with pub:
pub opaque type Name { ... } // OKopaque type Name { ... } // parse error. Opaque requires pubpub opaque fn foo() {} // parse error. Opaque only applies to types