2016-08-27 7 views
0

はここで生のポインタからSizedタイプを核変換する方法の例です:生のポインタから「サイズ付きタイプ」を作成するにはどうすればよいですか?

use std::mem; 

#[derive(Eq, PartialEq)] 
#[repr(packed)] 
struct Bob { 
    id: u32, 
    age: u32, 
} 

unsafe fn get_type<'a, T: Sized>(p: *const u8) -> &'a T { 
    mem::transmute(p) 
} 

#[test] 
fn it_works() { 
    let bob = Bob { 
     id: 22, 
     age: 445, 
    }; 
    let bob2: &Bob = unsafe { 
     let ptr: *const u8 = mem::transmute(&bob); 
     get_type(ptr) 
    }; 
    assert_eq!(&bob, bob2); 
} 

しかし、私のアプリケーションのために、私が代わりにSizedタイプの?Sized種類を取得できるようにしたいです。しかし、これは動作しません:

unsafe fn get_type2<'a, T: ?Sized>(p: *const u8) -> &'a T { 
    mem::transmute(p) 
} 

それは、このエラーメッセージで失敗します。私はstd::slice::from_raw_partsを使用して、それを変換することによってそれを&[u8](ファットポインタ)を与えることを試みたが、それが失敗した

error: transmute called with differently sized types: *const u8 (64 bits) to &'a T (pointer to T) [--explain E0512] 
--> src/main.rs:2:9 
    |> 
2 |>   mem::transmute(p) 
    |>   ^^^^^^^^^^^^^^ 

かなり同じエラーメッセージが表示されます。

答えて

6

エラーメッセージに記載されている理由のために実際にはできません。

錆の参照は(Sizedタイプの)ポインタサイズまたは!Sizedタイプの)大きくいずれかであり得ます。例えば、Traitが形質である場合、&Traitの参照は、実際には、std::raw::TraitObjectによって定義されるような2つのフィールドである。だから、

、無サイズ型への参照を形成するために、あなたがする必要があります。

  • は(?形質のスライス...)それは無サイズタイプのまさにどのような特定
  • 選びます右の表現(std::raw::TraitObjectstd::raw::Slice、...)

、その後、あなたは空白を埋めるために持っているが(単なるポインタよりもあります)。

したがって、関数を&T where T: Sizedに限定することができない限り、生ポインタを&Tにトランスレートするだけではできません。

+0

だから、コンパイラは普通のユースケースのすべてのことを魔法のように扱いますと思いますか? (それは '' Sized''がコンパイラ組み込みであることを意味しています...) - 'Sized'と' 'Sized'を意味すると思います。 – vitiral

+3

@cloudformdesign:私は'!Sized'を意味しました。 'Sized'はサイズを意味し、'!Sized'はサイズではない(実際にはバインドとして使用することはできません)、 '?Sized'は多分サイズを意味します。 'raw :: TraitObject'と' raw :: Slice'の両方が根本的な表現の進化を可能にする原則として不安定であり、おそらくRustが安定したABI。 –

+0

すごい! – vitiral

関連する問題