Skip to content

Investigate implementing Drop, removing Clone + Copy #10

@melody-rs

Description

@melody-rs

See #9

I'd like to implement Drop for FMOD types and get rid of the Clone + Copy impls. They're not very rusty and kind of a pain.
An API like this would let us do that:

impl System {
  fn create_dsp_by_type(&self, kind: DspType) -> Result<Owned<Dsp>>;
}

impl DspConnection {
  fn get_input(&self) -> Result<&Dsp>;
}

impl Dsp
  fn add_input(&self, input: &Dsp, kind: DspConnectionType) -> Result<DspConnection>;
}

impl Drop for Dsp { ... }

It falls apart in this sort of situation though:

let dsp1 = system.create_dsp(...)?;
let dsp2 = system.create_dsp(...)?;

let conn = dsp1.add_input(&dsp2, ...)?;

let dsp2_ref = conn.get_input()?;
drop(dsp2);

// dsp2_ref is now invalid, we've got a use after free!

FMOD has guardrails preventing this in my testing? And if Miri is ok with the below code, which mirrors what FMOD is doing using references, this API should be sound.

Miri is perfectly ok with this code:

#[derive(Clone, Copy, Debug)]
struct Hidden;

fn main() {
    let unhidden = Box::new(0_u128);
    // go from some inner "hidden" type to a zst
    let hidden = unsafe { 
        &*std::ptr::from_ref(&unhidden).cast::<Hidden>()
    };
    // release the inner type
    drop(unhidden);
    // the zst is still valid (according to miri)
    println!("{:?}", *hidden);
}

However, Miri isn't ok with this:

#[derive(Clone, Copy, Debug)]
struct Hidden;

fn main() {
    let unhidden = 0_u128;
    // go from inner type to hidden
    let hidden = unsafe {
        &*std::ptr::from_ref(&unhidden).cast::<Hidden>()
    };
    println!("{:?}", *hidden);
    // go back to the inner type (this is what FMOD would be doing)
    let unhidden = unsafe { 
        &*std::ptr::from_ref(hidden).cast::<u128>()
    };
    println!("{}", unhidden);
}

That last cast is what Miri doesn't like, but that's what FMOD is doing. Rust has no idea of that, so maybe its ok in practice?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions