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

RFC: #[derive(SmartPointer)] #3621

Merged
merged 16 commits into from
Jul 11, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions text/3621-derive-smart-pointer.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,8 @@ The macro sets the following requirements on its input:
2. The struct must have at least one type parameter. If multiple type
parameters are present, exactly one of them has to be annotated with the
`#[pointee]` derive helper attribute.
3. The struct must not be `#[repr(packed)]` or `#[repr(C)]`.
4. Other than one-aligned, zero-sized fields, the struct must have exactly one
field.
3. The struct must be `#[repr(transparent)]`.
4. The struct must have at least one field.
Darksonn marked this conversation as resolved.
Show resolved Hide resolved
5. Assume that `T` is a type that can be unsized to `U`, and let `FT` and `FU`
be the type of the struct's field when the pointee is equal to `T` and `U`
respectively. If the struct's trait bounds are satisfied for both `T` and
Expand All @@ -276,9 +275,10 @@ The macro sets the following requirements on its input:

(Adapted from the docs for [`DispatchFromDyn`].)

Point 1 and 2 are verified syntactically by the derive macro, whereas 3, 4 and 5
Point 1 and 2 are verified syntactically by the derive macro. Points 4 and 5
are verified semantically by the compiler when checking the generated
[`DispatchFromDyn`] implementation as it does today.
[`DispatchFromDyn`] implementation as it does today. Point 3 is verified by
introducing a new unstable helper trait `AssertReprTransparent`.

The `#[pointee]` attribute may also be written as `#[smart_pointer::pointee]`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the idea of an informal snake_case/CamelCase correspondence, but I still want to identify something more disciplined here than just than informal correspondence.

E.g. can we treat the underlying idea here that the SmartPointer "thing" being derived is a lang item coming from core::smart_pointer::SmartPointer?

Alternative, could the elaborated #[pointee] attribute be written as #[SmartPointer::pointee]?

I basically want to push back very lightly against grabbing both SmartPointer and smart_pointer without having some relationship between them as items in the modules provided by core.


Expand Down Expand Up @@ -331,6 +331,16 @@ where
T: ::core::marker::Unsize<U>,
{}
```
The macro will also generate an implementation of the new
`AssertReprTransparent` helper trait. The implementation will have the same
trait bounds as the struct definition.
```rust
#[automatically_derived]
impl<'a, T, A> ::core::ops::AssertReprTransparent for MySmartPointer<'a, T, A>
where
T: ?Sized + SomeTrait<T>,
{}
```
Darksonn marked this conversation as resolved.
Show resolved Hide resolved

## `Receiver` and `Deref` implementations

Expand Down Expand Up @@ -390,6 +400,13 @@ Although this RFC proposes to add the `PinCoerceUnsized` trait to ensure that
unsizing coercions of pinned pointers cannot be used to cause unsoundness, the
RFC does not propose to stabilize the trait.

## `AssertReprTransparent`

To verify the requirement that the struct is `#[repr(transparent)]`, we
introduce a new unstable marker trait called `AssertReprTransparent`. This trait
will be a lang item, and the compiler will emit an error if the trait is used
with a type that is not `#[repr(transparent)]`.

# Drawbacks
[drawbacks]: #drawbacks

Expand Down Expand Up @@ -715,6 +732,27 @@ This RFC does not propose it because it is a breaking change and the
discussed in more details in [the pre-RFC for stabilizing the underlying
traits][pre-rfc].

## `AssertReprTransparent`

When you implement the [`DispatchFromDyn`] trait, the compiler enforces various
things about the type to verify that it makes sense to implement
`DispatchFromDyn`. One of the things that the compiler verifies is that the
struct must not be `#[repr(packed)]` or `#[repr(C)]`.

However, because `#[derive(SmartPointer)]` has more narrow use-case than
`DispatchFromDyn`, we would like to restrict it further so that the macro only
works with `#[repr(transparent)]` types. To do this, we use a new trait called
`AssertReprTransparent` that verifies that the struct is `#[repr(transparent)]`
like how `DispatchFromDyn` verifies that the struct must not be
`#[repr(packed)]` or `#[repr(C)]`.

We cannot change the logic in `DispatchFromDyn` because some existing standard
library types cannot be `#[repr(transparent)]`. For example, this includes
`Box<T, A>` due to its allocator field.

This requirement may be relaxed in the future, in which case
`AssertReprTransparent` can be removed again.

# Prior art
[prior-art]: #prior-art

Expand Down