Skip to content

Commit 2c8ff4f

Browse files
conradludgateehuss
authored andcommitted
slight restructure
1 parent aeb9d4c commit 2c8ff4f

File tree

1 file changed

+44
-34
lines changed

1 file changed

+44
-34
lines changed

src/subtyping.md

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,7 @@ or permit undefined behavior.
77
In order to allow flexible usage of lifetimes
88
while also preventing their misuse, Rust uses a combination of **Subtyping** and **Variance**.
99

10-
## Subtyping
11-
12-
Subtyping is the idea that one type can be used in place of another.
13-
14-
Let's define that `Sub` is a subtype of `Super` (we'll be using the notation `Sub: Super` throughout this chapter)
15-
16-
What this is suggesting to us is that the set of *requirements* that `Super` defines
17-
are completely satisfied by `Sub`. `Sub` may then have more requirements.
18-
19-
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)
20-
21-
```rust
22-
use std::fmt;
23-
24-
pub trait Error: fmt::Display {
25-
fn source(&self) -> Option<&(dyn Error + 'static)>;
26-
fn description(&self) -> &str;
27-
fn cause(&self) -> Option<&dyn Error>;
28-
}
29-
```
30-
31-
Here, we have that `Error: fmt::Display` (`Error` is a *subtype* of `Display`),
32-
because it has all the requirements of `fmt::Display`, plus the `source`/`description`/`cause` functions.
33-
34-
However, subtyping in traits is not that interesting in the case of Rust.
35-
Here in the nomicon, we're going to focus more with how subtyping interacts with **lifetimes**
36-
37-
Take this example
10+
Let's start with a example.
3811

3912
```rust
4013
fn debug<T: std::fmt::Debug>(a: T, b: T) {
@@ -68,16 +41,53 @@ This would be rather unfortunate. In this case,
6841
what we want is to accept any type that lives *at least as long* as `'b`.
6942
Let's try using subtyping with our lifetimes.
7043

71-
Let's define a lifetime to have the a simple set of requirements:
44+
## Subtyping
45+
46+
Subtyping is the idea that one type can be used in place of another.
47+
48+
Let's define that `Sub` is a subtype of `Super` (we'll be using the notation `Sub: Super` throughout this chapter)
49+
50+
What this is suggesting to us is that the set of *requirements* that `Super` defines
51+
are completely satisfied by `Sub`. `Sub` may then have more requirements.
52+
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)
54+
55+
```rust
56+
use std::fmt;
57+
58+
pub trait Error: fmt::Display {
59+
fn source(&self) -> Option<&(dyn Error + 'static)>;
60+
fn description(&self) -> &str;
61+
fn cause(&self) -> Option<&dyn Error>;
62+
}
63+
```
64+
65+
Here, we have that `Error: fmt::Display` (`Error` is a *subtype* of `Display`),
66+
because it has all the requirements of `fmt::Display`, plus the `source`/`description`/`cause` functions.
67+
68+
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
70+
71+
Let's define a lifetime to be the simple requirement:
7272
`'a` defines a region of code in which a value will be alive.
7373
Now that we have a defined set of requirements for lifetimes, we can define how they relate to each other.
74-
`'a: 'b` if and only if `'a` defines a region of code that **completely contains** `'b`.
74+
`'long: 'short` if and only if `'long` defines a region of code that **completely contains** `'short`.
7575

76-
`'a` may define a region larger than `'b`, but that still fits our definition.
77-
Going back to our example above, we can say that `'static: 'b`.
76+
`'long` may define a region larger than `'short`, but that still fits our definition.
7877

79-
For now, let's accept the idea that subtypes of lifetimes can be passed through references (more on this in [Variance](#variance)),
80-
eg. `&'static str` is a subtype of `&'b str`, then we can let them coerce, and then the example above will compile
78+
> As we will see throughout the rest of this chapter,
79+
subtyping is a lot more complicated and subtle than this,
80+
but this simple rule is a very good 99% intuition.
81+
And unless you write unsafe code, the compiler will automatically handle all the corner cases for you.
82+
83+
> But this is the Rustonomicon. We're writing unsafe code,
84+
so we need to understand how this stuff really works, and how we can mess it up.
85+
86+
Going back to our example above, we can say that `'static: 'b`.
87+
For now, let's also accept the idea that subtypes of lifetimes can be passed through references
88+
(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
8191

8292
```rust
8393
fn debug<T: std::fmt::Debug>(a: T, b: T) {

0 commit comments

Comments
 (0)