How can we make this crate support ?Sized?

selfref is a nightly-only crate we made which lets us have more flexible self-ref structs than what was available with alternatives (see also Pain-free self-referential pinned types - selfref (nightly only)).

however, we'd really like to have dyn Trait support. we tried to do it with selfref 0.2.0 but it doesn't seem to work. any ideas how we might be able to pull it off?

also related: qcell + selfref? · Issue #37 · uazu/qcell · GitHub (this also includes a failing example of our attempts to use ?Sized, in the 2nd comment).

apparently we ran into Unsizing coercion does not normalize associated types in structs. · Issue #75899 · rust-lang/rust · GitHub aka unsizing fails when associated types are involved · Issue #50213 · rust-lang/rust · GitHub so we just need to... throw more nightly at it? we're not sure what to do here.

edit: ah just gotta wait now. ^^

alright so it turns out we're not done yet. we uh.

it does work with ?Sized except selfref::opaque! doesn't. for example:

error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> src/lib.rs:105:5
    |
105 | /     selfref::opaque! {
106 | |         impl[T: ?Sized] Opaque for IntrusiveLCellKey<T> {
    | |              - this type parameter needs to be `std::marker::Sized`
107 | |             type Kind<'this> = IntrusiveLCell<'this, T>;
108 | |         }
109 | |     }
    | |_____^ doesn't have a size known at compile-time
    |
note: required because it appears within the type `IntrusiveLCell<'_, T>`
   --> src/lib.rs:100:12
    |
100 |     struct IntrusiveLCell<'a, T: ?Sized> {
    |            ^^^^^^^^^^^^^^
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
    = note: this error originates in the macro `selfref::opaque` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
106 -         impl[T: ?Sized] Opaque for IntrusiveLCellKey<T> {
106 +         impl[T] Opaque for IntrusiveLCellKey<T> {
    |

This happens because of how we expand the "UB check":

#[macro_export]
macro_rules! opaque {
    (
        impl Opaque for $key:ty {
            type Kind<$l:lifetime> = $kind:ty;
        } $(where $($bounds:tt)*)?
    ) => {
        unsafe impl $crate::Opaque for $key $(where $($bounds)*)? {
            type Kind<$l> = $kind where Self: $l;
            fn ub_check() {
                fn ub_detect_helper(
                    _f: impl ::core::ops::Fn(
                        for<$l> fn([&$l (); 0]) -> $kind,
                        for<$l> fn(&$l $kind)
                    )
                ) $(where $($bounds)*)? {
                }
                ub_detect_helper(|f, g| {
                    let _foo: Self::Kind<'_> = f([]);
                    g(&_foo);
                });
            }
        }
    };
    (
        impl[$($params:tt)+] Opaque for $key:ty {
            type Kind<$l:lifetime> = $kind:ty;
        } $(where $($bounds:tt)*)?
    ) => {
        unsafe impl<$($params)+> $crate::Opaque for $key
        $(where $($bounds)*)? {
            type Kind<$l> = $kind where Self: $l;
            fn ub_check() {
                fn ub_detect_helper<$($params)+>(
                    _f: impl ::core::ops::Fn(
                        for<$l> fn([&$l (); 0]) -> $kind,
                        for<$l> fn(&$l $kind)
                    )
                ) $(where $($bounds)*)? {
                }
                ub_detect_helper(|f, g| {
                    let _foo: Self::Kind<'_> = f([]);
                    g(&_foo);
                });
            }
        }
    };
}

and we're honestly not sure how to ever fix this.

(we cannot use PhantomData here because PhantomData is unsound.)

we just used a Box and to maintain no-alloc we made it opt-in.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.