2016-08-11 22 views
2

Readが必要な関数に引数として&[u8]を指定しようとすると、以下の例のように正常に動作しないようです。std :: io :: readにキャスト&[u8]が原因の問題が発生しました。

use std::io::Read; 

fn main() { 
    let bytes: &[u8] = &[1, 2, 3, 4]; 
    print_reader(&bytes); 
} 

fn print_reader(reader: &(Read + Sized)) { 
    for byte in reader.bytes() { 
     println!("{}", byte.unwrap()); 
    } 
} 

コンパイラエラー:

impl<'a> Read for &'a [u8]

error: the trait bound `std::io::Read + Sized: std::marker::Sized` is not satisfied [--explain E0277] 
--> <anon>:9:24 
9 |>  for byte in reader.bytes() { 
    |>      ^^^^^ 
note: `std::io::Read + Sized` does not have a constant size known at compile-time 

error: the trait bound `std::io::Read + Sized: std::marker::Sized` is not satisfied [--explain E0277] 
--> <anon>:9:5 
9 |>  for byte in reader.bytes() { 
    |> ^
note: `std::io::Read + Sized` does not have a constant size known at compile-time 
note: required because of the requirements on the impl of `std::iter::Iterator` for `std::io::Bytes<std::io::Read + Sized>` 

error: aborting due to 2 previous errors 

Rust playground

次形質実装はstd::sliceドキュメントに記載されています。

答えて

2

I と思われます。これはむしろ役に立たないエラーメッセージです。私が説明しようとするでしょう:


まず:あなたは形質オブジェクト&Sizedを持つことができません。これはfirst object safety ruleに違反し、実際には意味をなさない。 Sized特性バインドを追加する唯一の理由は、すべてのSizedタイプの特別なプロパティを使用することです(スタックに保存するなど)。この例では、プロパティを使用しようとしています:

fn foo(x: &Sized) { 
    let y = *x; 
} 

yのサイズは?コンパイラは、他の特性オブジェクトと同様に、知ることができません。だから、我々はSizedという唯一の目的を特質オブジェクトと一緒に使うことはできない。したがって、特性オブジェクト&Sizedは役に立たず、実際に存在することはできません。

この場合、エラーメッセージは、少なくとも一種の私たちに正しい事伝えます:

error: the trait `std::marker::Sized` cannot be made into an object [--explain E0038] 
--> <anon>:7:1 
7 |> fn foo(x: &Sized) { 
    |>^
note: the trait cannot require that `Self : Sized` 

さらにを:私はあなたがすでに同じエラーを回避するためにバインドされ+ Sizedを、追加疑いますあなたが引数がreader: &Readだったときに現れました。ここでは、詳細なエラーの説明から一つの重要な洞察は次のとおりです。Bytesイテレータはすべての単一のバイトに一度Read::read()を呼び出すためRead::bytesため

Generally, Self : Sized is used to indicate that the trait should not be used as a trait object.

この制限は、意味を成しません。この関数呼び出しが仮想/動的関数呼び出しである場合、関数呼び出しのオーバーヘッドはバイトを実際に処理するよりもはるかに高くなります。


そう...は、なぜあなたはとにかく形質オブジェクトとしてReadを持っている必要がありますか?多くの場合、それは十分だ(いずれにしてもはるかに高速)ジェネリック医薬品を経由して、これを処理するために:

fn print_reader<R: Read>(reader: R) { 
    for byte in reader.bytes() { 
     println!("{}", byte.unwrap()); 
    } 
} 

これは動的ディスパッチを回避し、型チェッカーオプティマイザとうまく動作します。

関連する問題