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

Improve Type-Coersion Documentation #843

Merged
merged 8 commits into from
Aug 31, 2020
Merged
Changes from 7 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
53 changes: 31 additions & 22 deletions src/type-coercions.md
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`.
Copy link
Contributor

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 because as 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.

Copy link
Contributor Author

@AloeareV AloeareV Aug 27, 2020

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.


Coercions are originally defined in [RFC 401] and expanded upon in [RFC 1558].

Copy link
Contributor

Choose a reason for hiding this comment

The 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

Expand All @@ -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&mdash;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
}
```

Expand Down Expand Up @@ -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*)
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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).

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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*)
Expand Down Expand Up @@ -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.
Expand All @@ -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