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

Arbitrary self types v2 #3519

Merged
merged 49 commits into from
May 6, 2024
Merged
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
38d358d
Arbitrary self types v2.
adetaylor Nov 1, 2023
d13c170
Reflect RFC PR number.
adetaylor Nov 1, 2023
827e3d4
Fix pointer parameter.
adetaylor Nov 1, 2023
efaf68c
Switch diagnostics to Diagnostic Items.
adetaylor Nov 2, 2023
47be87b
Adding example to motivation section as requested.
adetaylor Nov 2, 2023
9607769
Adding extra motivation suggested by @clarfonthey.
adetaylor Nov 2, 2023
c7e917d
Provide example of current arbitrary_self_types.
adetaylor Nov 2, 2023
ce4aa78
Explain that the example is abridged.
adetaylor Nov 3, 2023
d3ea0b3
Note method candidacy of &T and &mut T.
adetaylor Nov 3, 2023
3f4493d
Note existing behavior of recursion.
adetaylor Nov 3, 2023
4a42fa3
Rewrite lifetime elision section.
adetaylor Nov 3, 2023
3577733
A bit more on lifetimes.
adetaylor Nov 3, 2023
e269c00
De-emphasize illegality of `&T`
adetaylor Nov 8, 2023
544f1af
Discuss recursion of traits.
adetaylor Nov 8, 2023
fad04ae
Ban generic receiver types.
adetaylor Nov 8, 2023
5e63e83
Tiny clarification.
adetaylor Nov 8, 2023
69b1edf
Emphasize that interop cases are about automation.
adetaylor Nov 8, 2023
7209586
Simplify introduction of motivation a little.
adetaylor Nov 8, 2023
1e97685
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 15, 2023
476d833
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 15, 2023
769c31b
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 16, 2023
f51948c
Clarify recursion point.
adetaylor Nov 21, 2023
d9f2316
Emphasize *const Self as receiver.
adetaylor Nov 22, 2023
750ec48
Rewrite Lifetime Elision section.
adetaylor Nov 22, 2023
0f6c0f6
Remove out-of-place paragraph.
adetaylor Nov 22, 2023
1859f95
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 22, 2023
156c535
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 22, 2023
4b8ba42
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 22, 2023
12eac0b
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 22, 2023
b962d2d
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 23, 2023
8b2b6df
Update text/3519-arbitrary-self-types-v2.md
adetaylor Nov 23, 2023
113c8bd
Update reference & deshadowing.
adetaylor Dec 21, 2023
9c59366
Include example lint.
adetaylor Feb 12, 2024
a5e274b
Update text/3519-arbitrary-self-types-v2.md
adetaylor Feb 14, 2024
7ea82bd
Move lint to the correct place.
adetaylor Feb 15, 2024
01c6ca7
Add future work section for MaybeUninit etc.
adetaylor Feb 15, 2024
09f46f7
Code error.
adetaylor Feb 15, 2024
6eb91e9
Suggestions for compiler changes section.
adetaylor Feb 15, 2024
13591a0
Merge pull request #19 from adetaylor/rewrite-reference-again
adetaylor Feb 15, 2024
e4fe352
Substantial rewrites.
adetaylor Apr 5, 2024
a436b1e
Merge pull request #20 from adetaylor/back-to-simple
adetaylor Apr 5, 2024
b367f59
Fix anchor error
adetaylor Apr 16, 2024
8d01878
Update text/3519-arbitrary-self-types-v2.md
adetaylor Apr 18, 2024
3413135
Fix a couple of mistakes
adetaylor Apr 18, 2024
a93ac4b
Fix link syntax.
adetaylor Apr 18, 2024
7c43c50
Update text/3519-arbitrary-self-types-v2.md
adetaylor Apr 19, 2024
5cec046
Update text/3519-arbitrary-self-types-v2.md
adetaylor Apr 19, 2024
131d7e9
Remove mention of impl Receiver for Vec
adetaylor Apr 19, 2024
ab248bb
Prepare RFC 3519 to be merged
traviscross May 6, 2024
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
51 changes: 43 additions & 8 deletions text/3519-arbitrary-self-types-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Allow types that implement the new `trait Receiver<Target=Self>` to be the recei

Today, methods can only be received by value, by reference, or by one of a few blessed smart pointer types from `core`, `alloc` and `std` (`Arc<Self>`, `Box<Self>`, `Pin<P>` and `Rc<Self>`).

It's been assumed that this will eventually be generalized to support any smart pointer, such as an `CustomPtr<Self>`. Since late 2017, it has been available on nightly under the `arbitrary_self_types` feature for types that implement `Deref<Target=Self>` and for raw pointers.
It's been assumed that this will eventually be generalized to support any smart pointer, such as an `CustomPtr<Self>`. Since late 2017, it has been available on nightly under the `arbitrary_self_types` feature for types that implement `Deref<Target=T>` and for raw pointers.

This RFC proposes some changes to the existing nightly feature based on the experience gained, with a view towards stabilizing the feature in the relatively near future.

Expand Down Expand Up @@ -83,20 +83,55 @@ See also [this blog post](https://medium.com/@adetaylor/the-case-for-stabilizing

## Motivation for the v2 changes

Unstable Rust contains an implementation of arbitrary self types based around the `Deref<Target=T>` trait. Naturally, that trait also provides a means to create a `&T`.
Unstable Rust contains an implementation of arbitrary self types based around the `Deref<Target=T>` trait. Naturally, that trait also provides a means to create a `&T`. Example:

However, if it's OK to create a reference `&T`, you _probably don't need this feature_. You can probably simply use `&self` as your receiver type.
```rust
#[feature(arbitrary_self_types)]

struct SmartPtr<T>(*const T);

impl<T: ?Sized> Deref for SmartPtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
// never called, but smart pointers need to implement this method
// sometimes it's just not safe to create a reference to self.0
}
}

struct ConcreteType;

impl ConcreteType {
fn some_method(self: SmartPtr<ConcreteType>) {

}
}

fn main() {
let concrete: SmartPtr<ConcreteType> = ...;
concrete.some_method();
}
```

However, if it's OK to create a reference `&T`, you _probably_ don't need this feature. You can simply use `&self` as your receiver type:

```rust
impl ConcreteType {
fn some_method(&self) {

}
}
```

This feature is fundamentally aimed at smart pointer types `P<T>` where it's not safe to create a reference `&T`. As noted above, that's most commonly because of semantic differences to pointers in other languages, but it might be because references have special meaning or behavior in some pure Rust domain. Either way, it's not OK to create a Rust reference `&T` or `&mut T`, yet we may want to allow methods to be called on some reference-like thing.
This feature is mostly aimed at smart pointer types `P<T>` where it's not safe to create a reference `&T`. As noted above, that's most commonly because of semantic differences to pointers in other languages, but it might be because references have special meaning or behavior in some pure Rust domain. Either way, it's not OK to create a Rust reference `&T` or `&mut T`, yet we may want to allow methods to be called on some reference-like thing.
adetaylor marked this conversation as resolved.
Show resolved Hide resolved

For this reason, implementing `Deref::deref` is problematic for _nearly everyone who wants to use arbitrary self types_.
For this reason, implementing `Deref::deref` is problematic for most of the likely users of this "arbitrary self types" feature.

If you're implementing a smart pointer `P<T>` yet you can't allow a reference `&T` to exist, any option for implementing `Deref::deref` has drawbacks:
If you're implementing a smart pointer `P<T>`, and you need to allow `impl T { fn method(self: P<T>) { ... }}`, yet you can't allow a reference `&T` to exist, any option for implementing `Deref::deref` has drawbacks:

* Specify `Deref::Target=T` and panic in `Deref::deref`. Not good.
* Specify `Deref::Target=*const T`. This works with the current arbitrary self types feature, but is only possible if your smart pointer type contains a `*const T` which you can reference - this isn't the case for (for instance) weak pointers or types containing `NonNull`.
* Specify `Deref::Target=*const T`. This is only possible if your smart pointer type contains a `*const T` which you can reference - this isn't the case for (for instance) weak pointers or types containing `NonNull`.

Therefore, the current Arbitrary Self Types v2 provides a separate `Receiver` trait.
Therefore, the current Arbitrary Self Types v2 provides a separate `Receiver` trait, so that there's no need to provide an awkward `Deref::deref` implementation.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation
Expand Down