Help refactor into Thread Safe dyn Trait

I'm having a bit of trouble moving my previously RefCell'ed code into a thread safe world. I'm coming across an error that has to do with dyn Traits, and I don't think the compiler is giving me that useful of information.

I saw and read a couple of posts on impl vs dyn, but I think this more has to do with the containers of Box, Muted, and Arc.

In the link below I have my previous implentation that works and the new impl that's doesn't. Any help would be appreciated.

This compiles on the playground:

enum SafeFile<'a> {
    UserDefined(Arc<Mutex<dyn Read + 'a>>),
}

impl SafeFile<'_> {
    fn write(&mut self /* and writer, etc */) {
        match self {
            SafeFile::UserDefined(file) => {
                let c = Arc::clone(file);
                let l = file.lock().unwrap();
-                add_bytes(*l);
+                add_bytes(&*l);
            }
        }
    }
}

fn safe_one<'a>(reader: impl Read + 'a) {
    let reader = Arc::new(Mutex::new(reader));
    let file = SafeFile::UserDefined(reader);
}

// same for both
- fn add_bytes(reader: impl Read /* and writer */) {
+ fn add_bytes(reader: &(impl Read + ?Sized) /* and writer */) {
    todo!()
}

Playground.

We have to relax the implicit Sized requirement (because trait objects are dynamically sized) and need to provide the trait object as reference (because we can't pass dynamically sized types around).

1 Like

This also works, without changing the definition of add_bytes, because &mut R implements Read whenever R does:

 impl SafeFile<'_> {
     fn write(&mut self /* and writer, etc */) {
         match self {
             SafeFile::UserDefined(file) => {
                 let c = Arc::clone(file);
-                let l = file.lock().unwrap();
-                add_bytes(*l);
+                let mut l = file.lock().unwrap();
+                add_bytes(&mut *l);
             }
         }
     }
 }
2 Likes

Thanks @2e71828 and @jofas for the answers!