1
- # Subtyping
1
+ # Subtyping and Variance
2
2
3
3
Subtyping is implicit and can occur at any stage in type checking or
4
4
inference. Subtyping in Rust is very restricted and occurs only due to
@@ -15,5 +15,75 @@ fn bar<'a>() {
15
15
let t : & 'a str = s ;
16
16
}
17
17
```
18
- Since ` 'static ` "lives longer" than ` 'a ` , ` &'static str ` is a subtype of
19
- ` &'a str ` .
18
+
19
+ Since ` 'static ` outlives the lifetime parameter ` 'a ` , ` &'static str ` is a
20
+ subtype of ` &'a str ` .
21
+
22
+ [ Higher-ranked]   ; [ function pointers] and [ trait objects] have another
23
+ subtype relation. They are subtypes of types that are given by substitutions of
24
+ the higher-ranked lifetimes. Some examples:
25
+
26
+ ``` rust
27
+ // Here 'a is substituted for 'static
28
+ let subtype : & (for <'a > fn (& 'a i32 ) -> & 'a i32 ) = & ((| x | x ) as fn (& _ ) -> & _ );
29
+ let supertype : & (fn (& 'static i32 ) -> & 'static i32 ) = subtype ;
30
+
31
+ // This works similarly for trait objects
32
+ let subtype : & (for <'a > Fn (& 'a i32 ) -> & 'a i32 ) = & | x | x ;
33
+ let supertype : & (Fn (& 'static i32 ) -> & 'static i32 ) = subtype ;
34
+
35
+ // We can also substitute one higher-ranked lifetime for another
36
+ let subtype : & (for <'a , 'b > fn (& 'a i32 , & 'b i32 ))= & ((| x , y | {}) as fn (& _ , & _ ));
37
+ let supertype : & for <'c > fn (& 'c i32 , & 'c i32 ) = subtype ;
38
+ ```
39
+
40
+ ## Variance
41
+
42
+ Variance is a property that generic types have with respect to their arguments.
43
+ A generic type's * variance* in a parameter is how the subtyping of the
44
+ parameter affects the subtyping of the type.
45
+
46
+ * ` F<T> ` is * covariant* over ` T ` if ` T ` being a subtype of ` U ` implies that
47
+ ` F<T> ` is a subtype of ` F<U> ` (subtyping "passes through")
48
+ * ` F<T> ` is * contravariant* over ` T ` if ` T ` being a subtype of ` U ` implies that
49
+ ` F<U> ` is a subtype of ` F<T> `
50
+ * ` F<T> ` is * invariant* over ` T ` otherwise (no subtyping relation can be
51
+ derived)
52
+
53
+ Variance of types is automatically determined as follows
54
+
55
+ | Type | Variance in ` 'a ` | Variance in ` T ` |
56
+ | -------------------------------| -------------------| -------------------|
57
+ | ` &'a T ` | covariant | covariant |
58
+ | ` &'a mut T ` | covariant | invariant |
59
+ | ` *const T ` | | covariant |
60
+ | ` *mut T ` | | invariant |
61
+ | ` [T] ` and ` [T; n] ` | | covariant |
62
+ | ` fn() -> T ` | | covariant |
63
+ | ` fn(T) -> () ` | | contravariant |
64
+ | ` std::cell::UnsafeCell<T> ` | | invariant |
65
+ | ` std::marker::PhantomData<T> ` | | covariant |
66
+ | ` Trait<T> + 'a ` | covariant | invariant |
67
+
68
+ The variance of other ` struct ` , ` enum ` , ` union ` and tuple types is decided by
69
+ looking at the variance of the types of their fields. If the parameter is used
70
+ 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 `
72
+ and ` U ` .
73
+
74
+ ``` rust
75
+ use std :: cell :: UnsafeCell ;
76
+ struct Variance <'a , 'b , T , U : 'a > {
77
+ x : & 'a U , // This makes `Variance` covariant in 'a, and would
78
+ // make it covariant in U, but U is used later
79
+ y : * const T , // Covariant in T
80
+ z : UnsafeCell <& 'b f64 >, // Invariant in 'b
81
+ w : * mut U , // Invariant in U, makes the whole struct invariant
82
+ }
83
+ ```
84
+
85
+ [ coercions ] : type-coercions.html
86
+ [ function pointers ] : types.html#function-pointer-types
87
+ [ Higher-ranked ] : ../nomicon/hrtb.html
88
+ [ lifetime bound ] : types.html#trait-object-lifetime-bounds
89
+ [ trait objects ] : types.html#trait-objects
0 commit comments