Custom pointer and unsized types
⚓ Rust 📅 2025-09-28 👤 surdeus 👁️ 7I need a smart pointer type that is basically a wrapper around Rc. Trying to make it work with unsized types I came across the following problem (Playground):
use std::rc::Rc;
struct Ptr<T: ?Sized>(Rc<T>);
impl<T: ?Sized> Ptr<T> {
    fn new(value: T) -> Self
    where
        T: Sized,
    {
        Self(Rc::new(value))
    }
    // Workaround for the lack of CoerceUnsized in stable rust.
    fn into_unsized<U>(self) -> Ptr<U>
    where
        U: ?Sized,
        Rc<T>: MyCoerceUnsized<U>,
    {
        Ptr(self.0.coerce())
    }
}
trait MyCoerceUnsized<U: ?Sized>: Sized {
    fn coerce(self) -> Rc<U>;
}
impl<A1, A2, R, F> MyCoerceUnsized<dyn Fn(A1, A2) -> R> for Rc<F>
where
    F: 'static + Fn(A1, A2) -> R,
{
    fn coerce(self) -> Rc<dyn Fn(A1, A2) -> R> {
        self
    }
}
fn tst1<F: 'static + Fn(&mut i32, &mut i32)>(f: F) -> Ptr<dyn Fn(&mut i32, &mut i32)> {
    // Error:
    // expected struct `Ptr<dyn for<'a, 'b> Fn(&'a mut i32, &'b mut i32)>`
    //    found struct `Ptr<dyn Fn(&mut i32, &mut i32)>`
    Ptr::new(f).into_unsized()
}
// This fails too.
fn tst2<F: 'static + for<'a, 'b> Fn(&'a mut i32, &'b mut i32)>(
    f: F,
) -> Ptr<dyn Fn(&mut i32, &mut i32)> {
    Ptr::new(f).into_unsized()
}
// And so does this.
fn tst3<F: 'static + for<'a, 'b> Fn(&'a mut i32, &'b mut i32)>(
    f: F,
) -> Ptr<dyn for<'a, 'b> Fn(&mut i32, &mut i32)> {
    Ptr::new(f).into_unsized()
}
// This works.
fn tst4<F: 'static + Fn(i32, i32)>(f: F) -> Ptr<dyn Fn(i32, i32)> {
    Ptr::new(f).into_unsized()
}
Am I missing something or is it a compiler bug?
2 posts - 2 participants
🏷️ Rust_feed