1- # Subtyping
1+ # Subtyping and Variance
22
33Subtyping is implicit and can occur at any stage in type checking or
44inference. Subtyping in Rust is very restricted and occurs only due to
@@ -15,5 +15,75 @@ fn bar<'a>() {
1515 let t : & 'a str = s ;
1616}
1717```
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