Is this method ok? Unsafe for dyncamic typing


#1

Hello,

I’m actually playing with dynamic typing through channel : I have channel of type “Any”.
I want to have a general function

get<T>(r: Receiver<...>) -> Box<T>

that returns the content of the receiver, casted in the type T.

I have a “working” version here, but it uses unsafe {}, and I wonder if it is correct.

I have, with the downcasting of Any,

&mut T

and I want to get

T

So I do

let x: &mut T = ...; //downcasting
let res = unsafe { mem::replace(x, mem::uninitialized::<T>()) }; // get ownership
mem::forget(x); // remove the uninitialized memory
return res; // End of the function

Is that going to provoke memory leaks, or erros?
Is there a better way to do that (without unsafe)?

Thank you in advance!

Denis


#2
    let mut s: Box<Any> = r.recv().unwrap();
    let s: &mut T = s.downcast_mut().unwrap();

The first s is shadowed by the borrow, later forget is called on the borrow instead of the actual Box, so its destructor will still be run, BOOM.

[deleted the following, then changed my mind and put it back]

forgetting a Box is a leak by definition. You’d want to deallocate it without running the inner destructor. Alternatively you can use std::raw::TraitObject to turn the data pointer into a new Box. Not sure if this is kosher.

This should be less broken but still glitches in the playpen in release mode.

fn get<T: Reflect + 'static>(r: &Receiver<Box<Any + Send>>) -> Box<T>{
    unsafe {
        let obj: Box<Any> = r.recv().unwrap();
        if !obj.is::<T>() {
            panic!("Type mismatch");
        }
        let raw: TraitObject = mem::transmute(Box::into_raw(obj));
        Box::from_raw(raw.data as *mut T)
    }
}   

#3

Wow, thank you for these good answer!
I still have so many to discover to write code like this…

Have a nice day!


#4

Pretty sure the issue is just that it takes longer to compile than the playpen’s timeout; compiling the entire std::mpsc module with optimizations is pretty expensive.


#5

Ahh, thanks, I’m less worried now :smile:
Substituting Vec for a channel seems to work out fine.