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