| This already happens all the time in rust, including in the standard library. The typical pattern is to define your CheckedType to be pub struct CheckedType(UncheckedType); e.g. where its inner field is private. Then, you only present safe constructors that check your invariant, and only provide methods that maintain the invariant. For a concrete example, String in rust is a Vec<u8> with the guarantee that the underlying bytes correspond to valid UTF8. Concretely, it is defined as #[derive(PartialEq, PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "String"]
pub struct String {
vec: Vec<u8>,
} You can construct a string from a vec of bytes via fn from_utf8(vec: Vec<u8>) -> Result<String, _>; as well as the unsafe method unsafe fun from_utf8_unchecked(vec: Vec<u8>) -> String; Note here that there isn't a separate capability/token though. This is typically viewed as bad practice in rust, as you can always ignore checking a capability/token. See for example rust's mutexes Mutex<T>, which carry the data (T) that you want access to themself. So, to get access to the data, you must call .lock(). There is a similar philosophy behind Rust's `Result` type. to get data underlying it, you must handle the possibility of an error somehow (which can include panicing upon detecting the error of course). |