mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-08 15:53:19 +00:00
Mostly this commit is about skipping wildcards that are redundant in some sense.
The motivation is that they looks `long` in Java code.
There are basically two important parts: return types and value parameters.
1. For return types default behaviour is skipping all declaration-site wildcards.
The intuition behind this rule is simple: return types are basically used in subtype position
(as an argument for another call), and here everything works well in case of 'out'-variance.
For example we have 'Out<Out<T>>>' as subtype both for 'Out<Out<T>>>' and 'Out<? extends Out<? extends T>>>',
so values of such type is more flexible in contrast to `Out<? extends Out<? extends T>>>` that could be used only
for the second case.
But we have choosen to treat `in`-variance in a different way: argument itself
should be rendered without wildcard while nested arguments are rendered by the rules
described further (see second part).
For example: 'In<Out<OpenClass>>' will have generic signature 'In<Out<? extends OpenClass>>'.
If we omit all wildcards here, then value of type 'In<Out<OpenClass>>'
will be impossible to use as argument for function expecting 'In<? super Out<? extends Derived>>'
where Derived <: OpenClass (you can check it manually :]).
And this exception should not be very inconvinient because in-variance is rather rare.
2. For value parameters we decided to skip wildcards if it doesn't make obtained signature weaker
in a sense of set of acceptable arguments.
More precisely:
a. We write wildcard for 'Out<T>' iff T ``can have subtypes ignoring nullability''
b. We write wildcard for 'In<T>' iff T is not equal to it's class upper bound (ignoring nullability again)
Definition of ``can have subtypes ignoring nullability'' is straightforward and you can see it in commit.
#KT-9801 Fixed
#KT-9890 Fixed
59 lines
1.6 KiB
Kotlin
Vendored
59 lines
1.6 KiB
Kotlin
Vendored
class OutPair<out X, out Y>
|
|
class In<in Z>
|
|
|
|
interface A {
|
|
fun foo1(x: OutPair<String, Int>)
|
|
fun foo2(x: OutPair<CharSequence, Int>)
|
|
|
|
fun foo3(x: In<String>)
|
|
fun foo4(x: In<Any>)
|
|
|
|
var prop1: OutPair<String, Int>
|
|
}
|
|
|
|
// method: A::foo1
|
|
// generic signature: (LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;)V
|
|
|
|
// method: A::foo2
|
|
// generic signature: (LOutPair<+Ljava/lang/CharSequence;Ljava/lang/Integer;>;)V
|
|
|
|
// method: A::foo3
|
|
// generic signature: (LIn<-Ljava/lang/String;>;)V
|
|
|
|
// method: A::foo4
|
|
// generic signature: (LIn<Ljava/lang/Object;>;)V
|
|
|
|
// method: A::getProp1
|
|
// generic signature: ()LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;
|
|
|
|
// method: A::setProp1
|
|
// generic signature: (LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;)V
|
|
|
|
abstract class B : A {
|
|
override final fun foo1(x: OutPair<String, Int>) {}
|
|
override final fun foo2(x: OutPair<CharSequence, Int>) {}
|
|
|
|
override final fun foo3(x: In<String>) {}
|
|
override final fun foo4(x: In<Any>) {}
|
|
|
|
override final var prop1: OutPair<String, Int> = null!!
|
|
}
|
|
|
|
// method: B::foo1
|
|
// generic signature: (LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;)V
|
|
|
|
// method: B::foo2
|
|
// generic signature: (LOutPair<+Ljava/lang/CharSequence;Ljava/lang/Integer;>;)V
|
|
|
|
// method: B::foo3
|
|
// generic signature: (LIn<-Ljava/lang/String;>;)V
|
|
|
|
// method: B::foo4
|
|
// generic signature: (LIn<Ljava/lang/Object;>;)V
|
|
|
|
// method: B::getProp1
|
|
// generic signature: ()LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;
|
|
|
|
// method: A::setProp1
|
|
// generic signature: (LOutPair<Ljava/lang/String;Ljava/lang/Integer;>;)V
|