Rustで引数型と戻り値型がSizedでなくてもよい条件
過去の記事でSized
について説明したが、関数の引数と戻り値についてはやや直感に反する条件が適用されているので説明する。
- 戻り値型: 関数やメソッドが本体をもつ場合に検査される。本体を持たない場合は
Sized
でなくてもよい。 - 引数型: それ自体は検査されない。関数やメソッドが本体を持つ場合は、引数を受け取るパターンに対する型検査が実行される。このとき、値が名前に束縛されていれば、束縛される名前の型が
Sized
でなければならない。
例
trait Foo { fn f(x: str) -> str; // OK // fn g(x: str) -> str { x } // error } fn h(_: str) {} // OK // fn i(x: str) -> str { x } // error fn j(ref x : str) {} // OK, but no way to call it fn main() { }
この規則は一見すると重箱的な問題のように見えるが、実は FnOnce
トレイトを見ると実際に活用されていることがわかる。
pub trait FnOnce<Args> { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; // ^^^^ Self : ?Sized }
トレイトの Self
引数だけは暗黙の Sized
境界が適用されないため、ここでは Self: ?Sized
である。(関連型は Sized
が適用される。)
この関数に Self: Sized
境界が必要ないのは、上記の条件のためである。