强制转换(Coercions)
在某些情况下,类型可以被隐含地强制改变.这些变化通常只会 削弱(weakening) 类型,主要集中在指针和生命周期.它们主要用于使Rust在更多情况下”正常工作(just work)”,并且在很大程度上是无害的.
这是所有种类的强制转换:
以下类型之间允许强制转换:
传递性(Transitivity):
T_1到T_3,其中T_1强制转换为T_2,T_2强制转换为T_3指针弱化(Pointer Weakening):
&mut T到&T*mut T到*const T&T到*const T&mut T到*mut T
无大小(Unsizing):如果
T实现CoerceUnsized<U>,则T到U解引用强制(Deref coercion):如果
T解引用为U(即T: Deref<Target=U>),则类型&T的表达式&x到类型&U的表达式&*x*函数指针的非捕获闭包(RFC 1558),例如
|| 8usize到fn() -> usize
CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U>是针对所有指针类型实现的(包括智能指针,如Box和Rc).Unsize仅自动实现,并启用以下转换:
[T; n]=>[T]T=>dyn Trait其中T: TraitFoo<..., T, ...>=>Foo<..., U, ...>其中:T: Unsize<U>Foo是一个结构只有
Foo的最后一个字段有涉及T的类型T不是任何其他字段的类型的一部分Bar<T>: Unsize<Bar<U>>,如果Foo的最后一个字段的类型为Bar<T>
强制转换发生在 强制地点(coercion site) .显式键入的任何位置都会导致对其类型的强制转换.如果需要进行推断,则不会进行强制转换.详尽地说,表达式e到类型U的强制地点是:
let语句,静态和常量:
let x: U = e函数参数:
takes_a_U(e)将返回的任何表达式:
fn foo() -> U { e }结构字面量:
Foo { some_u: e}数组字面量:
let x: [U; 10] = [e, ..]元组字面量:
let x: (U, ..) = (e, ..)块中的最后一个表达式:
let x: U = { ..; e }
请注意,匹配traits时不执行强制转换(接收者(receivers)除外,见下文).如果有某种类型U的impl并且T强制转为U,那么这不构成T的实现.例如,以下将不会通过类型检查,即使t可以强制转换为&T并且存在&T的impl:
trait Trait {}fn foo<X: Trait>(t: X) {}impl<'a> Trait for &'a i32 {}fn main() {let t: &mut i32 = &mut 0;foo(t);}
error[E0277]: the trait bound `&mut i32: Trait` is not satisfied--> src/main.rs:9:5|9 | foo(t);| ^^^ the trait `Trait` is not implemented for `&mut i32`|= help: the following implementations were found:<&'a i32 as Trait>note: required by `foo`--> src/main.rs:3:1|3 | fn foo<X: Trait>(t: X) {}| ^^^^^^^^^^^^^^^^^^^^^^error: aborting due to previous error
