Skip to content

Commit ee4f10a

Browse files
committed
modify variance section
1 parent a7bafe5 commit ee4f10a

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

src/subtyping.md

+29-3
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,46 @@ Variance of types is automatically determined as follows
6565
| `std::marker::PhantomData<T>` | | covariant |
6666
| `dyn Trait<T> + 'a` | covariant | invariant |
6767

68-
The variance of other `struct`, `enum`, `union`, and tuple types is decided by
68+
The variance of other `struct`, `enum`, and `union` types is decided by
6969
looking at the variance of the types of their fields. If the parameter is used
7070
in positions with different variances then the parameter is invariant. For
71-
example the following struct is covariant in `'a` and `T` and invariant in `'b`
71+
example the following struct is covariant in `'a` and `T` and invariant in `'b`, `'c`,
7272
and `U`.
7373

7474
```rust
7575
use std::cell::UnsafeCell;
76-
struct Variance<'a, 'b, T, U: 'a> {
76+
struct Variance<'a, 'b, 'c, T, U: 'a> {
7777
x: &'a U, // This makes `Variance` covariant in 'a, and would
7878
// make it covariant in U, but U is used later
7979
y: *const T, // Covariant in T
8080
z: UnsafeCell<&'b f64>, // Invariant in 'b
8181
w: *mut U, // Invariant in U, makes the whole struct invariant
82+
83+
f: fn(&'c ()) -> &'c () // Both co- and contravariant, makes 'c invariant
84+
// in the struct.
85+
}
86+
```
87+
88+
When used outside of an `struct`, `enum`, or `union`, the variance for parameters is checked at each location separately.
89+
90+
```rust
91+
fn generic_tuple<'short, 'long: 'short>(
92+
// 'long is used inside of a tuple in both a co- and invariant position.
93+
x: (&'long u32, UnsafeCell<&'long u32>)
94+
) {
95+
// As the variance at these positions is computed separately,
96+
// we can freely shrink 'long in the covariant position.
97+
let _: (&'short u32, UnsafeCell<&'long u32>) = x;
98+
}
99+
100+
fn takes_fn_ptr<'short, 'middle: 'short>(
101+
// 'middle is used in both a co- and contravariant position.
102+
f: fn(&'middle ()) -> &'middle ()
103+
) -> {
104+
// As the variance at these positions is computed separately,
105+
// we can freely shrink 'middle in the covariant position
106+
// and extend it in the contravariant position.
107+
let _: fn(&'static ()) -> &'short () = f;
82108
}
83109
```
84110

0 commit comments

Comments
 (0)