The underdogs of memory in Rust std::mem

9li8pj

(Updated from time to time -- feedback)
I'm just trying to list and uncover some simple safe and unsafe memory functions, please correct me if i used a wrong term somewhere i would be happy to edit

mem::take and mem::replace:

  • std::mem::replace swaps a value with a new one and returns the old value without taking ownership
  • std::mem::take is literally replace(dest, T::default()) so it takes the value out and replaces it with its default value

mem::ManuallyDrop and mem::forget

  • mem::ManuallyDrop is a wrapper type(struct) that make sure it's contents won't be automatically dropped, it can be dropped by using ManuallyDrop::drop or take the value out by ManuallyDrop::into_inner
    it is ?Sized to be able to handle dynamic types(dyn traits, str, [T]) and of course it can accept sized types too so it's very flexible,
  • mem::forget :shushing_face:
pub const fn forget<T>(t: T) {
    let _ = ManuallyDrop::new(t);
}

the only difference is that mem::forget takes ownership of T so it can never be dropped manually again,

mem::transmute, mem::transmute_copy

  • std::mem::transmute allows you to reinterpret or transmute raw bytes of a type into another in short 'zero-cost type casting', and it moves(ownership not in memory) the value, it enforces size at compile time(i got it wrong at first but the comment below corrected me).
    Example usage in rust core library:
    pub const fn as_bytes(&self) -> &[u8] {
        unsafe { mem::transmute(self) }
    }
    pub const fn from_bits(v: u16) -> Self {
        // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
        unsafe { mem::transmute(v) }
    }
  • std::mem::transmute_copy 'type casting' without moving the value, it compares and gurantees that both types have the same size at compile time sized
    ------------------------------------------------------------------

Help: i usually dig into functions through my vim bindings <leader>gd(go definition) to go to a function definition but the issue is that at a deeper level some functions are 'compiler intrinsic' so the compiler handles them behind the scenes for example

#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst {
    unreachable!()
}

so where can i find and navigate to this kind of functions?

Are you planning to publish this as a tutorial, or is this for your own learning? If the latter, I suggest changing the title's category to Help.

transmute is essentially equal[1] to this:

pub unsafe fn transmute<Src, Dst>(src: Src) -> Dst {
    let src = std::mem::ManuallyDrop::new(src);
    std::ptr::read((&raw const src).cast::<Dst>())
}

From the docs:

transmute is semantically equivalent to a bitwise move of one type into another. It copies the bits from the source value into the destination value, then forgets the original.


  1. modulo some safety checks ↩ī¸Ž

1 Like

transmute does check for size equality (and doesn't allow/can't deal with generics in other ways I don't remember off the top of my head).

transmute_copy didn't check sizes until this PR (and apparently the docs were never updated). It still allows the destination to be larger than the source, i.e., it doesn't enforce the same size.

1 Like

I don't know why you say "without taking ownership". The doc for the function is:

Moves src into the referenced dest, returning the previous dest value.
Neither value is dropped.

It follows from that description that ownership is changed. The dest location will own the value passed as src. The previous dest value is returned, so it will be owned by the caller -- this is true for any value returned by a function.

that sounds right, thanks, i've looked further and still couldn't find it in the source code

Great thanks, what really confused me is that transmute accepts dyn Trait which is dynamically sized, but what i didn't realize was that although dyn Trait is DST, the dyn trait itself is just a sized fat pointer, so we can transmute it to another fat pointer,
pretty confusing i think when we mention "dyn trait" generally we refer to it's underlying data not itself.
<3

When we mention dyn Trait, we usually actually mean the dyn Trait, i.e. the dynamically-sized thing. What can be transmuted (well, in theory, since its layout is unspecified) is a reference to dyn Trait.

1 Like

yeah i think calling it a reference to a dyn Trait is more accurate

Sorry i didn't see your reply earlier.
Actually i though about it but didn't see this fitting into any category.
<3

The Tutorials category is for telling people about tutorials that you've published. Unfortunately that's not documented -- the category description is empty.

If you don't want to use Help for some reason, there is always the Uncategorized category.

1 Like

that actually sounds right, i will change it right now.
thank you