tl;dr在Rust中是否有一个" strong ";类型别名(或输入机制),这样rustc
编译器将拒绝(发出一个错误)搞混,可能是相同的底层类型?
问题当前,可以定义相同底层类型的类型别名
type WidgetCounter = usize;
type FoobarTally = usize;
然而,如果我错误地混淆了两个类型别名的实例,编译器将不会拒绝(发出错误或警告)。
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);
}
(锈操场)
可能的解决方案?
我希望有一个额外的关键字strong
strong type WidgetCounter = usize;
strong type FoobarTally = usize;
使得前面的代码在编译时会导致编译错误:
error[E4444]: mismatched strong alias type WidgetCounter,
expected a FoobarTally
或者可能有一个聪明的技巧与struct
s可以实现这一点?
还是定义宏来完成此操作的装载模块?
我知道我可以"破解";这是通过类型混叠不同的数字类型,即i32
,然后u32
,然后i64
,等等。但是,由于许多原因,这是一个丑陋的hack。
是否有一种方法可以让编译器帮助我避免这些自定义类型别名混淆?
Rust有一个很好的技巧,叫做New Type Idiom。通过在元组结构中包装单个项,可以创建一个"强"结构。或";distinct"包装类型。
在Rust文档的元组结构部分也简要地提到了这个习语。
New Type Idiom"林克有一个很好的例子。这里有一个类似于您正在寻找的类型:
// 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);
}