Custom pointer and unsized types

⚓ Rust    📅 2025-09-28    👤 surdeus    👁️ 7      

surdeus

Warning

This post was published 33 days ago. The information described in this article may have changed.

I 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

Read full topic

🏷️ Rust_feed