Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Box<trait> have a different size than Box<struct>?

Consider the code:

use std::boxed::Box;
use std::mem::transmute;

trait Total {
    fn total(&self) -> i32;
}

#[derive(Debug)]
struct S {
    a: i32,
    b: i32,
    c: i32,
}

impl S {
    fn new() -> S {
        S { a: 2, b: 3, c: 4 }
    }
}

impl Total for S {
    fn total(&self) -> i32 {
        self.a + self.b + self.c
    }
}

fn main() {
    let b: Box<Total> = Box::new(S::new());
    unsafe {
        let s: Box<S> = std::mem::transmute(b);
        println!("S = {:?}", s);
    }
}

This gives the error:

error[E0512]: transmute called with differently sized types: Box<Total> (128 bits) to Box<S> (64 bits)
  --> src/main.rs:30:29
   |
30 |             let s: Box<S> = std::mem::transmute(b);
   |                             ^^^^^^^^^^^^^^^^^^^

Given that Box<Total> is really a Box<S>, why do we get this error?

like image 265
doron Avatar asked Oct 23 '16 12:10

doron


2 Answers

Unlike most languages featuring OO-concepts which embed virtual pointers in class, Rust uses the fat-pointer approach in which it carries both the virtual pointer and struct pointer alongside each other.

As a result, the layout of Box<Trait> for a S is:

+-------+-------+
| v-ptr | S-ptr |
+-------+-------+

which is 128-bits on a 64-bits platform.


As for downcasting, at the moment you can use the Any type and its downcast_ref and downcast_mut.

You may also be interested in the query_interface crate for more elaborate use cases.

like image 158
Matthieu M. Avatar answered Oct 12 '22 21:10

Matthieu M.


A trait object, such as Box<Trait> or &Trait, contains two pointers:

  • A pointer to the data
  • A pointer to the vtable

Two pointers (on 64-bit machines) adds up to 128 bits.

A Box<Struct> only contains a single pointer, directly to the data. No vtable is needed because the specific methods are able to be resolved statically at compile time. This single pointer is only 64 bits.

Given that Box<Total> is really a Box<S>

They are not. If they were the same, why would they have different names? :-)

like image 33
Shepmaster Avatar answered Oct 12 '22 19:10

Shepmaster