Skip to content

as cast improvements #1732

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

Merged
merged 4 commits into from
Feb 11, 2025
Merged
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
54 changes: 27 additions & 27 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,35 +454,35 @@ Any cast that does not fit either a coercion rule or an entry in the table is a
Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in
reference types and `mut` or `const` in pointer types.

| Type of `e` | `U` | Cast performed by `e as U` |
|-----------------------|-----------------------|----------------------------------|
| Integer or Float type | Integer or Float type | Numeric cast |
| Enumeration | Integer type | Enum cast |
| `bool` or `char` | Integer type | Primitive to integer cast |
| `u8` | `char` | `u8` to `char` cast |
| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast |
| `*T` where `T: Sized` | Integer type | Pointer to address cast |
| Integer type | `*V` where `V: Sized` | Address to pointer cast |
| `&m₁ T` | `*m₂ T` \*\* | Reference to pointer cast |
| `&m₁ [T; n]` | `*m₂ T` \*\* | Array to pointer cast |
| [Function item] | [Function pointer] | Function item to function pointer cast |
| [Function item] | `*V` where `V: Sized` | Function item to pointer cast |
| [Function item] | Integer | Function item to address cast |
| [Function pointer] | `*V` where `V: Sized` | Function pointer to pointer cast |
| [Function pointer] | Integer | Function pointer to address cast |
| Closure \*\*\* | Function pointer | Closure to function pointer cast |

\* 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 (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`).

\*\* only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference to
| Type of `e` | `U` | Cast performed by `e as U` |
|-----------------------|-----------------------|-------------------------------------------------------|
| Integer or Float type | Integer or Float type | [Numeric cast][expr.as.numeric] |
| Enumeration | Integer type | [Enum cast][expr.as.enum] |
| `bool` or `char` | Integer type | [Primitive to integer cast][expr.as.bool-char-as-int] |
| `u8` | `char` | [`u8` to `char` cast][expr.as.u8-as-char] |
| `*T` | `*V` [^meta-compat] | [Pointer to pointer cast][expr.as.pointer] |
| `*T` where `T: Sized` | Integer type | [Pointer to address cast][expr.as.pointer-as-int] |
| Integer type | `*V` where `V: Sized` | [Address to pointer cast][expr.as.int-as-pointer] |
| `&m₁ [T; n]` | `*m₂ T` [^lessmut] | Array to pointer cast |
| `*m₁ [T; n]` | `*m₂ T` [^lessmut] | Array to pointer cast |
| [Function item] | [Function pointer] | Function item to function pointer cast |
| [Function item] | `*V` where `V: Sized` | Function item to pointer cast |
| [Function item] | Integer | Function item to address cast |
| [Function pointer] | `*V` where `V: Sized` | Function pointer to pointer cast |
| [Function pointer] | Integer | Function pointer to address cast |
| Closure [^no-capture] | Function pointer | Closure to function pointer cast |

[^meta-compat]: where `T` and `V` have compatible metadata:
Copy link
Member

Choose a reason for hiding this comment

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

This being a footnote makes it really difficult to actually find this information. Why is it not just present in the pointer-to-pointer cast section as proper text?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you expand on this being difficult to find? You can just click the footnote link, right?

The reason it's not in pointer-to-pointer cast section is that it's a requirement, rather than effect.

I wish footnotes would be rendered where they are defined, rather than at the bottom. And if it's impossible I suppose we could refactor this so it doesn't use footnotes...

Copy link
Member

Choose a reason for hiding this comment

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

I don't know or expect to have to click the footnote to find fundamental information about how the cast behaves, especially when there's already a non-footnote section about the behaviour of the cast. Footnotes are for "unimportant" extra bits of important information, not main parts of the text.

Copy link
Member

Choose a reason for hiding this comment

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

The little footnote indicator is also just really easy to miss as part of a big table of information. (But even if I had noticed it I would not have clicked on it to try and find this information)

Copy link
Member Author

Choose a reason for hiding this comment

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

If the notes would be right next to the table, would that work for you?

this page rendered on doc.rust-lang.org/reference with footnotes moved right next to the table

Copy link
Member

Choose a reason for hiding this comment

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

Honestly I could still imagine missing it, when I see that table my first instinct is to click on the "Pointer to pointer casts" header to see all information about pointer to pointer casts. Having the footnotes right below would definitely be an improvement though

* `V: Sized`, or
* Both slice metadata (`*[u16]` -> `*[u8]`, `*str` -> `*(u8, [u32])`), or
* 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 (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`)

[^lessmut]: only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference/pointer to
`const` pointer is allowed.

\*\*\* only for closures that do not capture (close over) any local variables
[^no-capture]: only for closures that do not capture (close over) any local variables can be casted to function pointers.

### Semantics

Expand Down