Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize derive(CoercePointee), RFC 3621 #133862

Closed
dingxiangfei2009 opened this issue Dec 4, 2024 · 1 comment
Closed

Stabilize derive(CoercePointee), RFC 3621 #133862

dingxiangfei2009 opened this issue Dec 4, 2024 · 1 comment
Labels
T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@dingxiangfei2009
Copy link
Contributor

cc @traviscross @Darksonn

Tracked by #123430

Stabilization: #133820

What is being proposed for stabilization

This stabilization report concerns the macro specified by RFC3621,
now called CoercePointee.

This macro enables the derivation of trait implementation of Unsize, CoerceUnsize and DispatchFromDyn traits, both of which are unstable at the moment, under a well-defined and structured schema, so that the users who would like to allow their custom type to admit unsizing coercion and use of dyn DST in one of its generic type parameter in a safe way. The greatest use case of this macro is to allow users to equip their types with this behaviour without dependence on alloc crate, or when alloc is not available and a custom implementation of pointer-like data structure in the likes of Rc and Arc is highly desirable. The most prominent example is the kernel crate by Rust-for-Linux, which would greatly benefit from this macro due to reduction of boilerplate, and reduce the project's dependence on unstable features behind Unsize, CoerceUnsize and DispatchFromDyn.

In a nutshell, derive(CoercePointee) derives the implementation of CoerceUnsize and DispatchFromDyn traits on the target struct definition with all the necessary trait bounds. It identifies one generic type variable in the generic list of the target struct, that is either uniquely annotated with the #[pointee] attribute or is the only type variable among the generics. This identified generic, which is called source type in this document, will be treated as the target of unsizing operation and dyn trait object dispatch. Correspondingly, the resultant type after the unsizing coercion will be called target type in this document. In case additional trait bounds applies on the source type, the said trait bounds will be migrated to both the source type and the target type in the trait implementation.

Out of necessity of unsizing coercion, the macro requires the struct to adopt the repr(transparent) layout. The only data field in the struct definition, which is required by this layout, should also implement CoerceUnsize and DispatchFromDyn at the moment, or at least conform to requirement of the unsizing coercion and trait object dispatching protocol.

As an example, here is how the generated code would look like after expanding the macro. The following is a user source that invokes this macro.

pub trait MyTrait<T: ?Sized> {}

#[derive(core::marker::CoercePointee)]
#[repr(transparent)]
pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>, X: MyTrait<T> = ()>
where
    Y: MyTrait<T>,
{
    data: &'a mut T,
    x: core::marker::PhantomData<X>,
}

This is the expansion result. The source type T after the unsizing coercion is assumed to be __S and the trait bounds requested by the original definition are migrated for __S as well throughtout.

#[repr(transparent)]
pub struct MyPointer2<
    'a, Y, Z: MyTrait<T>,
    #[pointee] T: ?Sized + MyTrait<T>,
    X: MyTrait<T> = ()
>
where Y: MyTrait<T>
{
    data: &'a mut T,
    x: core::marker::PhantomData<X>,
}

#[automatically_derived]
impl<
    'a, Y,
    Z: MyTrait<T> + MyTrait<__S>,
    T: ?Sized + MyTrait<T> + ::core::marker::Unsize<__S>,
    __S: ?Sized + MyTrait<__S>,
    X: MyTrait<T> + MyTrait<__S>
>
::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>> for MyPointer2<'a, Y, Z, T, X>
where Y: MyTrait<T>, Y: MyTrait<__S> {
}

#[automatically_derived]
impl<
    'a, Y,
    Z: MyTrait<T> + MyTrait<__S>,
    T: ?Sized + MyTrait<T> + ::core::marker::Unsize<__S>,
    __S: ?Sized + MyTrait<__S>,
    X: MyTrait<T> + MyTrait<__S>
>
::core::ops::CoerceUnsized<MyPointer2<'a, Y, Z, __S, X>> for MyPointer2<'a, Y, Z, T, X>
where Y: MyTrait<T>, Y: MyTrait<__S> {
}

Future interaction

This stabilization of this macro does not require the stabilization of any of the unstable traits mentioned. This macro aims at stabilising a subset of features thereof, which has widely proliferated in the ecosystem, without blocking further development of DSTs and unsizing coercion. In case of change in the design of these language features, as long as basic provision of the coercion operation remains the same, the macro should be updated to use the new facility inside its implementation when necessary, to preserve only the semantics and capabilities that this macro exposes users to.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Dec 4, 2024
@traviscross traviscross added T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Dec 4, 2024
@traviscross
Copy link
Contributor

Closing in favor of:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants