型強制
特定の状況では、暗黙に型変換を強制することが出来ます。これらの変換は、一般には 単に型を弱くしていて、主にポインタやライフタイム周りに着目されます。 これらはほとんどが、より多くのケースで Rust が "単に動く" ようにするために存在し、 そして大部分において、ほとんど害はありません。
これらは全ての種類の型強制です:
型強制は以下の型の間で認められています:
- 推移性:
T_1からT_3但しT_1がT_2に型強制可能で、T_2がT_3に型強制可能な場合 - ポインタの弱化:
&mut Tから&T*mut Tから*const T&Tから*const T&mut Tから*mut T
- アンサイジング:
TからU但しTがCoerceUnsized<U>を実装している場合 - 参照外しの型強制: 型
&Tの式&xから型&Uの式&'x但しTがUに参照外しされる場合 (例:T: Deref<Target=U>)
CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U> は
全てのポインタ型 (Box や Rc のようなスマートポインタを含む) で実装されています。
アンサイズは自動的にのみ実装され、以下の変換を有効にします。
[T; n]=>[T]T=>Trait但しT: TraitFoo<..., T, ...>=>Foo<..., U, ...>但しT: Unsize<U>Fooは構造体Fooの最後のフィールドだけがTを含む型であるTは他のフィールドの一部となっていないBar<T>: Unsize<Bar<U>>但しFooの最後のフィールドがBar<T>の型である場合
型強制は、型強制サイトで起こります。明確に型が指定されている全ての場所で、
その型への型強制が発生します。もし推論が必要ならば、型強制は行われません。
余すことなく言えば、式 e に対する型 U への型強制サイトは以下の通りです。
- let 文、 static、 const:
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 }
トレイトをマッチさせる場合、型強制が行われないことに注意してください (レシーバは例外です、
以下を見てください) 。もしある型 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);
}
<anon>:10:5: 10:8 error: the trait bound `&mut i32 : Trait` is not satisfied [E0277]
(エラー: トレイト境界 `&mut i32: Trait` が満たされていません)
<anon>:10 foo(t);
^~~