2016-08-21 2 views
1

Ich versuche, die Funktionalität von CoerceUnsized zu verwenden:können nicht verschachtelte zwingen, so bemessen, dass unsized Typ mit CoerceUnsized

use std::rc::Rc; 
use std::borrow::Borrow; 

fn main() { 
    // Create (sized) i32 wrapped in an rc. 
    let a0: Rc<i32> = Rc::new(0i32); 
    // Coerce to (unsized) Borrow<i32> wrapped in an rc. 
    // Works fine in Beta and Nightly cause of CoerceUnsized. 
    let a1: Rc<Borrow<i32>> = a0.clone(); 

    // Create (sized) i32 in nested rcs. 
    let b0: Rc<Rc<i32>> = Rc::new(Rc::new(0i32)); 
    // Coerce to (unsized) Borrow<i32> in nested rcs. 
    // Does not compile in Stable, Beta or Nightly. 
    let b1: Rc<Rc<Borrow<i32>>> = b0.clone(); 

    println!("{}, {}", a1.borrow(), b1.borrow()); 
} 

Playground

Aber die verschachtelte coerce von Rc<Rc<i32>> zu Rc<Rc<Borrow<i32>>> nicht kompilieren.

Warum funktioniert CoerceUnsized nicht rekursiv? Gibt es Workarounds, wie explizites Casting?

Antwort

4

eine Rc<i32> zu Rc<Borrow<i32>> Konvertierung erfordert nichts weiter als neben dem Rc einen VTable-Zeiger hinzugefügt, und es wirkt sich nicht auf die von der Rc verwalteten Speicher. Auf der anderen Seite würde das Umwandeln von Rc<Rc<i32>> zu Rc<Rc<Borrow<i32>> bedeuten, dass der VTable-Zeiger neben dem inneren Rc verdeckt wird. Dies würde das Modifizieren (und Vergrößern) des Speichers erfordern, der von dem äußeren Rc verwaltet wird (d. H. Es würde effektiv eine ganz neue Zuweisung erfordern). Sie könnten dies manuell tun, aber es ist weit über den Rahmen eines Zwanges hinaus.

+0

Ist das im Wesentlichen der gleiche Grund, warum Sie nicht 'Vec >' '' '' & [& [T]] '' zwingen können - würde der mittlere Artikel die Größe ändern? – Shepmaster

+0

Ok, du hast Recht, der Typ 'Rc ' 'benötigt irgendwo einen Vtable-Zeiger. Aber der Punkt ist, dass der Zwang von 'Rc >' zu 'Rc >' NICHT dazu führt, dass der vtable-Zeiger auf dem Heap neben dem i32 ist. Im Falle einer Umwandlung von "& i32" in "& Borrow " wird der vtable-Zeiger stattdessen neben jeder Referenz gehalten. Ich vermute also, dass die vtable-Zeiger immer neben der äußersten Verschachtelungsebene stehen. Und dies würde diese Art der Umwandlung ermöglichen. Bin ich wirklich falsch? – Pentagolo

+0

@Pentagolo Nein, der Vtable-Zeiger befindet sich neben der * innersten * Verschachtelungsebene (gut, die innerste gültige Ebene — 'RefCell >' zum Beispiel ist nur ein anderer nicht-typisierter Typ, kein Verweis, neben dem ein VTable-Zeiger gespeichert werden könnte) .) – delnan

Verwandte Themen