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,71 @@ 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 ` 'a ` , ` &'static str ` is a subtype of ` &'a str ` .
20
+
21
+ Subtyping also exists for [ higher-ranked types] . Replacing a higher ranked
22
+ lifetime with a concrete lifetime produces a subtype.
23
+
24
+ ``` rust
25
+ fn bar () {
26
+ // Explicitly f: for<'a> fn(&'a i32) -> &'a i32.
27
+ let f : fn (& i32 ) -> & i32 = | x | x ;
28
+ let g : fn (& 'static i32 ) -> & 'static i32 = f ;
29
+ }
30
+ ```
31
+
32
+ The subtype must be a valid type:
33
+
34
+ ``` rust,compile_fail
35
+ fn bar<'a>() {
36
+ let h: for<'b, 'c> fn(&'c &'b i32) -> &'b i32 = |x| &**x;
37
+ let j: fn(&'static &'a i32) -> &'a i32 = h;
38
+ // Error: in type `&'static &'a i32`, reference has a longer lifetime than
39
+ // the data it references
40
+ }
41
+ ```
42
+
43
+ ## Variance
44
+
45
+ Variance is a property that generic types have with respect to their arguments.
46
+ A generic type's * variance* in a parameter is how the subtyping of the
47
+ parameter affects the subtyping of the type.
48
+
49
+ * ` F<T> ` is * covariant* over ` T ` if ` T ` being a subtype of ` U ` implies that
50
+ ` F<T> ` is a subtype of ` F<U> ` (subtyping "passes through")
51
+ * ` F<T> ` is * contravariant* over ` T ` if ` T ` being a subtype of ` U ` implies
52
+ that ` F<U> ` is a subtype of ` F<T> `
53
+ * ` F<T> ` is * invariant* over ` T ` otherwise (no subtyping relation can be derived)
54
+
55
+ Variance of types is automatically determined as follows
56
+
57
+ * ` &'a T ` is covariant in ` 'a ` and ` T ` .
58
+ * ` &'a mut T ` is covariant in ` 'a ` , invariant in ` T ` .
59
+ * ` [T] ` and ` [T; n] ` are covariant in ` T ` .
60
+ * ` *const T ` is covariant in ` T ` .
61
+ * ` *mut T ` is invariant in ` T ` .
62
+ * ` fn(T) -> U ` is covariant in ` U ` and contravariant in ` T ` .
63
+ * ` std::cell::UnsafeCell<T> ` is invariant in ` T ` .
64
+ * ` std::marker::PhantomData<T> ` is covariant in ` T ` .
65
+ * Trait objects are invariant in their type parameters and associated types and
66
+ covariant in their [ lifetime bound] .
67
+
68
+ The variance of ` struct ` , ` enum ` , ` union ` and tuple types is decided by looking
69
+ at the variance of the types of their fields. If a type parameter is used more
70
+ than once then the more restrictive variance is used. For example the following
71
+ struct is covariant in ` 'a ` and ` T ` and invariant in ` 'b ` and ` U ` .
72
+
73
+ ``` rust
74
+ use std :: cell :: UnsafeCell ;
75
+ struct Variance <'a , 'b , T , U : 'a > {
76
+ x : & 'a U ,
77
+ y : * const T ,
78
+ z : UnsafeCell <& 'b f64 >,
79
+ w : * mut U ,
80
+ }
81
+ ```
82
+
83
+ [ coercions ] : type-coercions.html
84
+ [ higher-ranked types ] : ../nomicon/hrtb.html
85
+ [ lifetime bound ] : types.html#trait-object-lifetime-bounds
0 commit comments