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

Add trait_upcasting related languages changes #1622

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 6 additions & 1 deletion src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,12 @@ reference types and `mut` or `const` in pointer types.
| [Function pointer] | Integer | Function pointer to address cast |
| Closure \*\*\* | Function pointer | Closure to function pointer cast |

\* or `T` and `V` are compatible unsized types, e.g., both slices, both the same trait object.
\* or `T` and `V` are unsized types with compatible metadata:
* both slice metadata (`*[u16]` -> `*[u8]`, `*str` -> `*(u8, [u32])`).
* both the same trait object metadata, modulo dropping auto traits (`*dyn Debug` -> `*(u16, dyn Debug)`, `*dyn Debug + Send` -> `*dyn Debug`).
* **Note**: *adding* auto traits is only allowed if the principal trait has the auto trait as a super trait
traviscross marked this conversation as resolved.
Show resolved Hide resolved
(given `trait T: Send {}`, `*dyn T` -> `*dyn T + Send` is valid, but `*dyn Debug` -> `*dyn Debug + Send` is not).
* **Note**: generics (including lifetimes) must match (`*dyn T<'a, A>` -> `*dyn T<'b, B>` requires `'a = 'b` and `A = B`).
Copy link
Contributor

Choose a reason for hiding this comment

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

Does as not permit upcasting?

Copy link
Member Author

Choose a reason for hiding this comment

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

as permits upcasting.


\*\* only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference to
`const` pointer is allowed.
Expand Down
13 changes: 12 additions & 1 deletion src/type-coercions.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,14 @@ r[coerce.unsize]

r[coerce.unsize.intro]
The following coercions are called `unsized coercions`, since they
relate to converting sized types to unsized types, and are permitted in a few
relate to converting types to unsized types, and are permitted in a few
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
relate to converting types to unsized types, and are permitted in a few
relate to converting sized types to unsized types or converting from one unsized type to another, and are permitted in a few

(more clarity, same meaning)

Copy link
Member Author

Choose a reason for hiding this comment

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

For me your proposed change kinda flushes the cache, I had to re-read it 4 times before I figured out what it means 💀 (then again, maybe I shouldn't be reading it at 3am)

Since it's the same meaning I'd think that more concise is better? Do you disagree?

cases where other coercions are not, as described above. They can still happen
anywhere else a coercion can occur.

r[coerce.unsize.misnomer]
> Note: "unsizing" is a bit of a misnomer,
> since this covers unsized->unsized coercions too.
Comment on lines +203 to +204
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
> Note: "unsizing" is a bit of a misnomer,
> since this covers unsized->unsized coercions too.
> Note: These are sometimes called "unsizing" coercions, but that can be a bit of a misnomer, since these cover unsized->unsized coercions too.

Not sure if something like this is what you meant to say or not. The Reference doesn't refer to "unsizing" anywhere -- even though, you're right, we often do in conversation -- so we'd need to introduce that somehow in this note.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm. There may not be the literal word "unsizing", but we do refer to this coercion as "unsize coercion".

The following coercions are called unsized coercions, since they

I do feel like it's clear what this means, given that this note is surrounded by mentions of unsize coercions. (but maybe not see you seem to be confused?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Although I'd also say that replacing "unsized coercion" to "unsizing coercion" everywhere in the reference would be a good idea. It sounds better and more closely matches how people actually talk about this feature.

Copy link
Contributor

Choose a reason for hiding this comment

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

In conversation with @traviscross, I was one of the confused ones. TC pointed out that "unsized coercion" can be interpreted as the codomain so to speak. That is, it doesn't seem like a misnomer to me because it is only referring to coercions to something not sized, and thus seemed accurate.

It is true the word "unsizing" implies "to remove the size of", that is the domain is sized, and thus is not always an accurate term. However, we don't use "unsizing" here.

Probably a bit of a muddled interpretation on my part, but does that make sense?

Copy link
Member

Choose a reason for hiding this comment

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

"unsized coercion" sounds like the coercion itself is unsized. I don't even know what that should mean.


r[coerce.unsize.trait]
Two traits, [`Unsize`] and [`CoerceUnsized`], are used
to assist in this process and expose it for library use. The following
Expand All @@ -211,6 +215,12 @@ r[coerce.unsize.slice]
r[coerce.unsize.trait-object]
* `T` to `dyn U`, when `T` implements `U + Sized`, and `U` is [dyn compatible].

r[coerce.unsize.trait-upcast]
Copy link
Member

@scottmcm scottmcm Dec 18, 2024

Choose a reason for hiding this comment

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

Is there worth saying anything here about whether this can change the value of the data pointer, or whether it can only change the vtable pointer?

(Maybe it's just a non-normative note, but contrasting with *const [i32]*const [i8] that doesn't change the metadata -- even though people sometimes expect it to -- sounds potentially useful.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this whole section might need a retractor :p

Specifically I think it should more clearly state the difference between Unsize and CoerceUnsize, mention that the former is not actually a coercion, and the latter is only for pointers.

Then it would also make sense to add a note that unsizing coercion changes the metadata of a pointer, while all other coercions/casts don't.

But, if you don't mind I'll leave this as a follow up ^^'

* `dyn T` to `dyn U`, when `U` is one of `T`'s [supertraits].
* This allows dropping auto traits, i.e. `dyn T + Auto` to `dyn U` is allowed.
WaffleLapkin marked this conversation as resolved.
Show resolved Hide resolved
* This allows adding auto traits if the principal trait has the auto trait as a super trait,
i.e. given `trait T: U + Send {}`, `dyn T` to `dyn T + Send` or to `dyn U + Send` coercions are allowed.

r[coerce.unsized.composite]
* `Foo<..., T, ...>` to `Foo<..., U, ...>`, when:
* `Foo` is a struct.
Expand Down Expand Up @@ -327,3 +337,4 @@ precisely.
[`Unsize`]: std::marker::Unsize
[`CoerceUnsized`]: std::ops::CoerceUnsized
[method-call expressions]: expressions/method-call-expr.md
[supertraits]: items/traits.md#supertraits
Loading