tl;dr在 Rust 中,是否存在“强”类型别名(或类型机制),使得rustc
编译器会拒绝(发出错误)可能是相同底层类型的混淆?
目前,可以定义相同底层类型的类型别名
type WidgetCounter = usize;
type FoobarTally = usize;
Run Code Online (Sandbox Code Playgroud)
但是,如果我错误地混淆了两种类型别名的实例,编译器不会拒绝(发出错误或警告)。
fn tally_the_foos(tally: FoobarTally) -> FoobarTally {
// ...
tally
}
fn main() {
let wc: WidgetCounter = 33;
let ft: FoobarTally = 1;
// whoops, passed the wrong variable!
let tally_total = tally_the_foos(wc);
}
Run Code Online (Sandbox Code Playgroud)
(铁锈游乐场)
我希望有一个额外的关键字之类的东西strong
strong type WidgetCounter = usize;
strong type FoobarTally = usize;
Run Code Online (Sandbox Code Playgroud)
这样前面的代码在编译时会导致编译器错误:
error[E4444]: mismatched strong alias type WidgetCounter,
expected a FoobarTally
Run Code Online (Sandbox Code Playgroud)
或者也许 s 有一个巧妙的技巧struct
可以实现这一点?
或者定义宏来完成此任务的货物模块?
我知道我可以通过类型别名不同的数字类型来“破解”这个,即i32
、 then u32
、 theni64
等。但由于很多原因,这是一个丑陋的黑客。
有没有办法让编译器帮助我避免这些自定义类型别名混淆?
小智 15
Rust 有一个很好的技巧,叫做New Type Idiom就是为了这个目的。通过将单个项目包装在元组结构中,您可以创建“强”或“不同”类型的包装器。
Rust 文档的元组结构部分也简要提到了这个习惯用法。
“新类型习语”链接有一个很好的例子。这是与您正在寻找的类型类似的一种:
// Defines two distinct types. Counter and Tally are incompatible with
// each other, even though they contain the same item type.
struct Counter(usize);
struct Tally(usize);
// You can destructure the parameter here to easily get the contained value.
fn print_tally(Tally(value): &Tally) {
println!("Tally is {}", value);
}
fn return_tally(tally: Tally) -> Tally {
tally
}
fn print_value(value: usize) {
println!("Value is {}", value);
}
fn main() {
let count: Counter = Counter(12);
let mut tally: Tally = Tally(10);
print_tally(&tally);
tally = return_tally(tally);
// This is a compile time error.
// Counter is not compatible with type Tally.
// print_tally(&count);
// The contained value can be obtained through destructuring
// or by potision.
let Tally(tally_value ) = tally;
let tally_value_from_position: usize = tally.0;
print_value(tally_value);
print_value(tally_value_from_position);
}
Run Code Online (Sandbox Code Playgroud)