-
Notifications
You must be signed in to change notification settings - Fork 496
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
Improve Type-Coersion Documentation #843
Changes from 7 commits
69af035
8983dcc
79e0589
5164816
95383ec
023b0db
21bffc2
d5372c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
# Type coercions | ||
|
||
Coercions are defined in [RFC 401]. [RFC 1558] then expanded on that. | ||
A coercion is implicit and has no syntax. | ||
**Type coercions** are implicit operations that change the type of a value. | ||
They happen automatically at specific locations and are highly restricted in | ||
what types actually coerce. | ||
|
||
The [type cast operator], `as`, is not a coersion site. However, most type | ||
conversions allowed by coersion can also be explicitly performed by `as`. | ||
|
||
Coercions are originally defined in [RFC 401] and expanded upon in [RFC 1558]. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to avoid double blank lines. |
||
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md | ||
[RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md | ||
|
||
## Coercion sites | ||
|
||
|
@@ -15,52 +19,53 @@ sites are: | |
|
||
* `let` statements where an explicit type is given. | ||
|
||
For example, `42` is coerced to have type `i8` in the following: | ||
For example, `&mut 42` is coerced to have type `&i8` in the following: | ||
|
||
```rust | ||
let _: i8 = 42; | ||
let _: &i8 = &mut 42; | ||
``` | ||
|
||
* `static` and `const` statements (similar to `let` statements). | ||
* `static` and `const` item declarations (similar to `let` statements). | ||
|
||
* Arguments for function calls | ||
|
||
The value being coerced is the actual parameter, and it is coerced to | ||
the type of the formal parameter. | ||
|
||
For example, `42` is coerced to have type `i8` in the following: | ||
For example, `&mut 42` is coerced to have type `&i8` in the following: | ||
|
||
```rust | ||
fn bar(_: i8) { } | ||
fn bar(_: &i8) { } | ||
|
||
fn main() { | ||
bar(42); | ||
bar(&mut 42); | ||
} | ||
``` | ||
|
||
For method calls, the receiver (`self` parameter) can only take advantage | ||
of [unsized coercions](#unsized-coercions). | ||
|
||
* Instantiations of struct or variant fields | ||
* Instantiations of struct, union, or enum variant fields | ||
|
||
For example, `42` is coerced to have type `i8` in the following: | ||
For example, `&mut 42` is coerced to have type `&i8` in the following: | ||
|
||
```rust | ||
struct Foo { x: i8 } | ||
struct Foo<'a> { x: &'a i8 } | ||
|
||
fn main() { | ||
Foo { x: 42 }; | ||
Foo { x: &mut 42 }; | ||
} | ||
``` | ||
|
||
* Function results, either the final line of a block if it is not | ||
* Function results—either the final line of a block if it is not | ||
semicolon-terminated or any expression in a `return` statement | ||
|
||
For example, `42` is coerced to have type `i8` in the following: | ||
For example, `x` is coerced to have type `&dyn Display` in the following: | ||
|
||
```rust | ||
fn foo() -> i8 { | ||
42 | ||
use std::fmt::Display; | ||
fn foo(x: &u32) -> &dyn Display { | ||
x | ||
} | ||
``` | ||
|
||
|
@@ -91,7 +96,7 @@ the block has a known type. | |
|
||
Coercion is allowed between the following types: | ||
|
||
* `T` to `U` if `T` is a subtype of `U` (*reflexive case*) | ||
* `T` to `U` if `T` is a [subtype] of `U` (*reflexive case*) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There seems to be an unanswered question here: https://github.com/rust-lang/reference/pull/342/files#r191050490 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've had little experience with the term 'reflexive' in programming contexts, but in math, "is a subset of" is a reflexive relationship. I assume that "is a subtype of" would be the programming equivalent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. I'm not super familiar with it, but since this is just adding a link, I won't hold up the PR on it. AIUI, the reflexive subtype would be "T is a subtype of T", not U (in the math sense, T is a subset of T). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess.. Subtyping is an example of a reflexive relationship, because types are subtypes of themselves. So.. That means that a subtype coersion is reflexive, because it could be coercing to Self. That sounds really finicky now that I say it. |
||
|
||
* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` | ||
(*transitive case*) | ||
|
@@ -164,8 +169,7 @@ an implementation of `Unsize<U>` for `T` will be provided: | |
|
||
* `[T; n]` to `[T]`. | ||
|
||
* `T` to `U`, when `U` is a trait object type and either `T` implements `U` or | ||
`T` is a trait object for a subtrait of `U`. | ||
* `T` to `dyn U`, when `T` implements `U + Sized`, and `U` is [object safe]. | ||
|
||
* `Foo<..., T, ...>` to `Foo<..., U, ...>`, when: | ||
* `Foo` is a struct. | ||
|
@@ -182,5 +186,10 @@ unsized coercion to `Foo<U>`. | |
> has been stabilized, the traits themselves are not yet stable and therefore | ||
> can't be used directly in stable Rust. | ||
|
||
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md | ||
[RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md | ||
[subtype]: subtyping.md | ||
[object safe]: items/traits.md#object-safety | ||
[type cast operator]: expressions/operator-expr.md#type-cast-expressions | ||
[`Unsize`]: ../std/marker/trait.Unsize.html | ||
[`CoerceUnsized`]: ../std/ops/trait.CoerceUnsized.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phrasing here seems a little strange to me. Nothing suggests or implies that
as
is a coercion site. The equivalence doesn't make sense becauseas
is an expression, not a location. It also says "most type conversions...", but then doesn't say which are allowed.I think it would be best just to keep this simple and to the point. I still suggest my original wording, something like
For explicit type coercions, see [type cast expressions].
.Also, the word is spelled "coercion" with a
c
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to make the distinction that, if it's explicit, it's not a coercion. You're right that that wording is funky, though.