Sizeof Option<Weak<T>>

fn test_00() {
    println!("size: {:?}", std::mem::size_of::<Option<Weak<u8>>>());
    println!("size: {:?}", std::mem::size_of::<Weak<u8>>());}

this outputs 8, 8.

So now my question is: how do we know if Option<Weak<T>> always uses that optimization trick to ensure that it output size 8 ?

1 Like

It looks like it isn't guarenteed, Weak isn't #[repr(transparent)]

1 Like

Can we construct a Struct or Enum where Option<Weak<T>> does not have size 8 bytes ?

If T is dynamically sized (i.e., !Sized), then Option<Weak<T>> is 16 bytes long on 64-bit systems:

use std::{mem, rc::Weak};
println!("{}", mem::size_of::<Option<Weak<[u8]>>>());
// prints 16

However, Option<Weak<T>> is generally going to be 8 bytes long when T: Sized, as a consequence of its definition:

pub struct Weak<T: ?Sized> {
    ptr: NonNull<RcBox<T>>,

The standard library reserves the right to change this definition in the future. As a historical note, the definition (or one of a few equivalent definitions) has been in place since commit 0d48f762243, which was included in Rust 1.0.0-alpha. So this program actually prints 16 on my machine when compiled on Rust 0.12.0:

use std::mem;
use std::rc::Weak;

fn main() {
    println!("{}", mem::size_of::<Option<Weak<u8>>>());
    // prints 8 on Rust 1.0.0-alpha and newer
    // prints 16 on Rust 0.12.0 and older
1 Like

Please correct me if I am wrong. This it not due to lack of Option<Weak> optimization, but instead due to "fat pointers".

That is correct; it requires 16 bytes to store the address (8 bytes) and the length (8 bytes) of the slice. Without the Option niche optimization, an Option<Weak<[u8]>> would require 24 bytes.

Also, if you want to guarantee that an Option<Weak<T>> only takes 8 bytes, you can use Weak::into_raw() + Weak::from_raw() to store it as a raw pointer.

Just jumping in to reiterate that

  • Without #[repr(transparent)], there's no guarantee the Option<_> size optimization goes through
  • Even if #[repr(transparent)] was added, the lib team doesn't necessarily consider that a guarantee they'll keep it that way either (as it's just sometimes necessary or desired, and there's no private way to add that attribution to a public type)
  • So in short the lib team is reserving the right to break this optimization

That said, people are conscious of the optimization so it would probably take a good reason to lose it.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.