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,71 @@ 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 ` '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