You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/md/kotlin.core/declarations.md
+112-30
Original file line number
Diff line number
Diff line change
@@ -1780,56 +1780,138 @@ Only type parameters of [inline functions][Inlining] can be declared `reified`.
1780
1780
1781
1781
#### Type parameter variance
1782
1782
1783
-
The [declaration-site variance][Mixed-site variance] of a particular type parameter for a classifier declaration is specified using special keywords `in` (forcovariant parameters) and `out` (forcontravariant parameters).
1783
+
The [declaration-site variance][Mixed-site variance] of a particular type parameter for a classifier declaration is specified using special keywords `in` (forcontravariant parameters) and `out` (forcovariant parameters).
1784
1784
If the variance isnot specified, the parameter is implicitly declared invariant.
1785
1785
See [the type system section][Mixed-site variance] for details.
1786
1786
1787
-
Atype parameter is**usedincovariant position**inthe following cases:
1787
+
We would consider a type expression `E` to be **covariant**intype parameter `X` iffor every concrete type expressions `T1` and `T2` such that `T1<:T2` it holds that `E[T1/X] <:E[T2/X]`. One could also say, that the *position* `X` takes in`E` is**covariant**.
1788
1788
1789
-
-Itis used as an argument in another generic type and the corresponding parameter in that type is covariant;
1790
-
-Itis the return type of a function;
1791
-
-Itis a type of a property.
1789
+
Not nested covariant cases are the following:
1792
1790
1793
-
A type parameter is**used in contravariant position**in the following cases:
1791
+
-A type expression is covariant in type parameter `X`, ifthis parameter is explicitly declared as `out` either [in the expression itself][Use-site variance] or [in the type declaration][Declaration-site variance];
1792
+
-Types of functions are covariant in their return type parameter, since functions have [types of kind][Function types] `FN<inA1, ..., inAN, outR>`);
1793
+
-Types of read-only properties are effectively in covariant position;
1794
1794
1795
-
-Itis used as an argument in another generic type and the corresponding parameter in that type is contravariant;
1796
-
-Itis a type of an parameter of a function;
1797
-
-Itis a type of a mutable property.
1795
+
In the same way, we would consider a type expression `E` to be **contravariant**in type parameter `X` iffor every concrete type expressions `T1` and `T2` such that `T1<:T2` it holds that `E[T2/X] <:E[T1/X]`.
1798
1796
1799
-
A type parameter is used in an invariant position if it is used as an argument in another generic type and the corresponding parameter in that type is invariant.
1797
+
Not nested contravariant cases are the following:
1798
+
1799
+
-A type expression is contravariant in type parameter `X`, ifthis parameter is explicitly declared as `in` either [in the expression itself][Use-site variance] or [in the type declaration][Declaration-site variance];
1800
+
-Types of functions are contravariant in their argument types, since functions have [types of kind][Function types] `FN<inA1, ..., inAN, outR>`;
1801
+
1802
+
Lastly, we would consider a type expression `E` to be **invariant**in type parameter `X` iffor every concrete type expressions `T1` and `T2`, `E[T1/X] <:E[T2/X]` holds ifand only if `T1=T2` (`T1<:T2` and `T2<:T1`).
1803
+
1804
+
Not nested invariant cases are the following:
1805
+
1806
+
-A type expression is invariant in type parameter `X`, ifthis parameter isnot declared as either `in` or `out` [in the expression itself][Use-site variance] or [in the type declaration][Declaration-site variance];
1807
+
-Types of mutable properties are effectively in invariant position;
1808
+
1809
+
We will use `+` as a symbol denoting contravariance, `-` as a symbol denoting covariance and `o` as a symbol denoting invariance.
1810
+
1811
+
To infer variance of a complex type expression in a type parameter, variance composition is used, which is defined as follows:
1812
+
1813
+
-Given two type expressions, `A<X>` and `B<Y>`, if variance of `A<X>` in `X` is `v1`, and variance of `B<Y>` in `Y` is `v2`, then the variance of `A<B<Y>>` in `Y` is $\texttt{v1} \otimes \texttt{v2} = \texttt{v3}$, which is defined in the following table:
1814
+
1815
+
\begin{align*}
1816
+
\texttt{+} \otimes x &= x \text{, where $x$ is any variance} \\
1817
+
\texttt{-} \otimes \texttt{+} &= \texttt{-} \\
1818
+
\texttt{-} \otimes \texttt{-} &= \texttt{-} \\
1819
+
\texttt{o} \otimes x &= \texttt{o} \text{, where $x$ is any variance} \\
1820
+
x \otimes \texttt{o} &= \texttt{o} \text{, where $x$ is any variance}
1821
+
\end{align*}
1822
+
1823
+
This can be interpreted in the following way:
1824
+
1825
+
-Covariance*preserves* the given variance
1826
+
-Contravariance*inverses* the given variance
1827
+
-Invariance*absorbs* the given variance
1828
+
1829
+
Using the base not-nested cases and the rules for combining variance, we can iteratively define for every type expression its variance in a given type parameter.
1830
+
1831
+
When a type parameter has declared variance, andis used in a position of a different variance, a **variance conflict** may occure. The specific cases are:
1832
+
1833
+
-A non-invariant type parameter is used as an argument to an invariant position;
1834
+
-A covariant type parameter is used as an argument to a contravariant position;
1835
+
-A contravariant type parameter is used as an argument to a covariant position;
1836
+
1837
+
Important remark: variance conflict does not occur if the containing declaration isprivate to the type parameter owner (in which case its visibility is restricted, see the [visibility][Declaration visibility] section for details).
1800
1838
1801
-
A usage of a contravariant type parameter in a covariant or invariant position, as well as usage of a covariant type parameter in a contravariant or invariant position, results in**variance conflict**and a compiler error, unless the containing declaration isprivate to the type parameter owner (in which case its visibility is restricted, see the [visibility][Declaration visibility] section for details).
1802
1839
This applies only to member declarations of the corresponding class, extensions are not subject to this limitation.
1803
1840
1804
1841
This restrictions may be lifted in particular cases by [annotating][Annotations] the corresponding type parameter usage with a special built-inannotation `kotlin.UnsafeVariance`.
1805
1842
By supplying thisannotation the author of the code explicitly declares that safety features that variance checks provide are not needed inthis particular declarations.
>// Variance of F1<in Foo<S>, out Unit> in S -- covariance
1899
+
> }
1900
+
>
1901
+
>classIn<inT>() // T is contravariant
1902
+
>classOut<outT>() // T is covariant
1903
+
>
1904
+
>classTest<inI, outO> {
1905
+
>funtest(a:In<In<I>>) {} // Ok, contravariant parameter in contravariant usage
1906
+
>// test has type F1<in In<In<I>>, out Unit>
1907
+
>// Need to find variance of F1<in In<In<I>>, out Unit> in I
1908
+
>// In<I> is contravariant (-) in I
1909
+
>// In<In<I>> is covariant in I, since - $\otimes$ - = + (covariance)
1910
+
>// F1<in In<In<I>>> is contravariant in I, since - $\otimes$ + = - (contravariance)
1911
+
> }
1912
+
> ```
1913
+
>
1914
+
>Remark: cases `e`, `f`, `f2`, `g`, `g2` inBasicExamples are also examples of variance composition, since they are read-only fields. However, since read-only fields are of covariance (`+`) andfor any variance $x$, $\texttt{+} \otimes x = x$, it was ommited at that point.
1833
1915
>
1834
1916
>Any of these restrictions may be lifted using `@UnsafeVariance` annotation on the type argument:
0 commit comments