Skip to content

Commit ea95076

Browse files
conradludgateehuss
authored andcommitted
address some grammatical comments
1 parent 8f88efd commit ea95076

File tree

1 file changed

+30
-25
lines changed

1 file changed

+30
-25
lines changed

src/subtyping.md

+30-25
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ However, a naive implementation of lifetimes would be either too restrictive,
55
or permit undefined behavior.
66

77
In order to allow flexible usage of lifetimes
8-
while also preventing their misuse, Rust uses a combination of **Subtyping** and **Variance**.
8+
while also preventing their misuse, Rust uses **subtyping** and **variance**.
99

10-
Let's start with a example.
10+
Let's start with an example.
1111

1212
```rust
13-
fn debug<T: std::fmt::Debug>(a: T, b: T) {
13+
fn debug<'a>(a: &'a str, b: &'a str) {
1414
println!("a = {:?} b = {:?}", a, b);
1515
}
1616

1717
fn main() {
1818
let hello: &'static str = "hello";
1919
{
2020
let world = String::from("world");
21-
let world = &world; // 'b has a shorter lifetime than 'static
21+
let world = &world; // 'world has a shorter lifetime than 'static
2222
debug(hello, world);
2323
}
2424
}
2525
```
2626

27-
In a conservative implementation of lifetimes, since `a` and `b` have differeing lifetimes,
27+
In a conservative implementation of lifetimes, since `hello` and `world` have differing lifetimes,
2828
we might see the following error:
2929

3030
```text
@@ -34,23 +34,25 @@ error[E0308]: mismatched types
3434
10 | debug(hello, world);
3535
| ^
3636
| |
37-
| expected `&'static str`, found struct `&'b str`
37+
| expected `&'static str`, found struct `&'world str`
3838
```
3939

4040
This would be rather unfortunate. In this case,
41-
what we want is to accept any type that lives *at least as long* as `'b`.
41+
what we want is to accept any type that lives *at least as long* as `'world`.
4242
Let's try using subtyping with our lifetimes.
4343

4444
## Subtyping
4545

4646
Subtyping is the idea that one type can be used in place of another.
4747

48-
Let's define that `Sub` is a subtype of `Super` (we'll be using the notation `Sub: Super` throughout this chapter)
48+
Let's define that `Sub` is a subtype of `Super` (we'll be using the notation `Sub: Super` throughout this chapter).
4949

5050
What this is suggesting to us is that the set of *requirements* that `Super` defines
5151
are completely satisfied by `Sub`. `Sub` may then have more requirements.
5252

53-
An example of simple subtyping that exists in the language are [supertraits](https://doc.rust-lang.org/stable/book/ch19-03-advanced-traits.html?highlight=supertraits#using-supertraits-to-require-one-traits-functionality-within-another-trait)
53+
An example of simple subtyping that exists in the language is [supertraits][supertraits]:
54+
55+
[supertraits]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait
5456

5557
```rust
5658
use std::fmt;
@@ -66,12 +68,15 @@ Here, we have that `Error: fmt::Display` (`Error` is a *subtype* of `Display`),
6668
because it has all the requirements of `fmt::Display`, plus the `source`/`description`/`cause` functions.
6769

6870
However, subtyping in traits is not that interesting.
69-
Here in the nomicon, we're going to focus more with how subtyping interacts with lifetimes
71+
Here in the Rustonomicon, we're going to focus more with how subtyping interacts with lifetimes.
7072

7173
Let's define a lifetime to be the simple requirement:
72-
`'a` defines a region of code in which a value will be alive.
73-
Now that we have a defined set of requirements for lifetimes, we can define how they relate to each other.
74-
`'long: 'short` if and only if `'long` defines a region of code that **completely contains** `'short`.
74+
75+
> `'a` defines a region of code.
76+
77+
Now that we have a defined set of requirements for lifetimes, we can define how they relate to each other:
78+
79+
> `'long : 'short` if and only if `'long` defines a region of code that **completely contains** `'short`.
7580
7681
`'long` may define a region larger than `'short`, but that still fits our definition.
7782

@@ -83,11 +88,11 @@ And unless you write unsafe code, the compiler will automatically handle all the
8388
> But this is the Rustonomicon. We're writing unsafe code,
8489
so we need to understand how this stuff really works, and how we can mess it up.
8590

86-
Going back to our example above, we can say that `'static: 'b`.
91+
Going back to our example above, we can say that `'static : 'world`.
8792
For now, let's also accept the idea that subtypes of lifetimes can be passed through references
8893
(more on this in [Variance](#variance)),
89-
eg. `&'static str` is a subtype of `&'b str`, then we can let them coerce,
90-
and then the example above will compile
94+
_e.g._ `&'static str` is a subtype of `&'world str`, then we can let a `&'static str` "downgrade" into a `&'world str`.
95+
With that, the example above will compile:
9196

9297
```rust
9398
fn debug<T: std::fmt::Debug>(a: T, b: T) {
@@ -98,16 +103,16 @@ fn main() {
98103
let hello: &'static str = "hello";
99104
{
100105
let world = String::from("world");
101-
let world = &world; // 'b has a shorter lifetime than 'static
102-
debug(hello, world); // a silently converts from `&'static str` into `&'b str`
106+
let world = &world; // 'world has a shorter lifetime than 'static
107+
debug(hello, world); // hello silently downgrades from `&'static str` into `&'world str`
103108
}
104109
}
105110
```
106111

107112
## Variance
108113

109-
Above, we glossed over the fact that `'static: 'b` implied that `&'static T: &'b T`. This uses a property known as variance.
110-
It's not always as simple as this example though, to understand that let's try extend this example a bit
114+
Above, we glossed over the fact that `'static : 'b` implied that `&'static T : &'b T`. This uses a property known as _variance_.
115+
It's not always as simple as this example, though. To understand that, let's try to extend this example a bit:
111116

112117
```rust,compile_fail
113118
fn assign<T>(input: &mut T, val: T) {
@@ -133,11 +138,11 @@ Our first instinct might be to blame the `assign` impl, but there's really nothi
133138
It shouldn't be surprising that we might want to assign a `T` into a `T`.
134139

135140
The problem is that we cannot assume that `&mut &'static str` and `&mut &'b str` are compatible.
136-
This must mean that `&mut &'static str` should **not** be a *subtype* of `&mut &'b str`,
141+
This means that `&mut &'static str` **cannot** be a *subtype* of `&mut &'b str`,
137142
even if `'static` is a subtype of `'b`.
138143

139-
Variance is the way that Rust defines the relationships of subtypes through their *type constructor*.
140-
A type constructor is any generic type with unbound arguments.
144+
Variance is the concept that Rust borrows to define relationships about subtypes through their *type constructor*s.
145+
A type constructor is any generic item in Rust.
141146
For instance `Vec` is a type constructor that takes a type `T` and returns
142147
`Vec<T>`. `&` and `&mut` are type constructors that take two inputs: a
143148
lifetime, and a type to point to.
@@ -244,15 +249,15 @@ Meanwhile, in the caller we pass in `&mut &'static str` and `&'spike_str str`.
244249
Because `&mut T` is invariant over `T`, the compiler concludes it can't apply any subtyping
245250
to the first argument, and so `T` must be exactly `&'static str`.
246251

247-
This is counter to the `&T` case
252+
This is counter to the `&T` case:
248253

249254
```rust
250255
fn debug<T: std::fmt::Debug>(a: T, b: T) {
251256
println!("a = {:?} b = {:?}", a, b);
252257
}
253258
```
254259

255-
Where similarly `a` and `b` must have the same type `T`.
260+
where similarly `a` and `b` must have the same type `T`.
256261
But since `&'a T` *is* covariant over `'a`, we are allowed to perform subtyping.
257262
So the compiler decides that `&'static str` can become `&'b str` if and only if
258263
`&'static str` is a subtype of `&'b str`, which will hold if `'static: 'b`.

0 commit comments

Comments
 (0)