8

オブジェクトの安全性の基本に苦労しています。このコードがあれば

struct S {
    x: i32,
}

trait Trait: Sized {
    fn f(&self) -> i32
    where
        Self: Sized;
}

fn object_safety_dynamic(x: Trait) {}

私は受け取ります

error[E0038]: the trait `Trait` cannot be made into an object
  --> src/lib.rs:11:29
   |
5  | trait Trait: Sized {
   |       -----  ----- ...because it requires `Self: Sized`
   |       |
   |       this trait cannot be made into an object...
...
11 | fn object_safety_dynamic(x: Trait) {}
   |                             ^^^^^ the trait `Trait` cannot be made into an object

: Sizedをスーパートレイトとして、または のバインドとして追加または削除すると、fわずかに異なるエラー メッセージが表示されます。

誰かが説明できますか:

  • この特定の例が機能しないのはなぜですか? 特徴オブジェクトの章では、次のように述べています。

    では、メソッドをオブジェクトセーフにするものは何ですか? 各メソッドは、Self: Sized

    満たされているのではないですか?

  • Trait: Sizedとはどう違いwhere Self: Sizedますか?(そうですね、一方はトレイトを継承し、もう一方はパラメーター バインドですが、Rust のトレイト オブジェクトの観点からは?

  • 私が仕事をしなければならなかった好ましい変更は何object_safety_dynamicですか?

気が向いrustc 1.19.0-nightly (01951a61a 2017-05-20)たら使っています。

固定サイズに関するコメントへの対応。

trait TraitB {
    fn f(&self) -> i32
    where
        Self: Sized;

    fn g<T>(&self, t: T) -> i32
    where
        Self: Sized;
}
4

2 に答える 2

5

Traitのスーパータイプを作成Sizedしても役に立ちません。実際、エラー メッセージにあるように、それは許可されていません。の実装ごとにサイズTrait異なるobject_safety_dynamicため、関数をコンパイルできません。汎用パラメーターがないため、ここではモノモーフィゼーションを使用できません。そのため、コンパイルされた関数は のすべての実装で機能する必要がありTraitます。

ただし、参照のサイズ固定されているため、引数を参照にすることは機能します。

trait Trait {
    fn f(&self) -> i32;
}

fn object_safety_dynamic(x: &Trait) {}

特性オブジェクトは、常に何らかの種類の参照です (例: aBox<T>または ) &T。これはまさに、参照型のサイズが既知の固定サイズであるのに対し、トレイトの実装のサイズが異なるためです。

于 2017-05-21T11:31:30.913 に答える