Build recursive raw types and raw types which contain type parameters properly
1) Substitute erasure of other type parameters 2) Use star projection at top level for recursive raw types ^KT-46126 Fixed
This commit is contained in:
+36
@@ -21142,6 +21142,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("errorType.kt")
|
||||
public void testErrorType() throws Exception {
|
||||
@@ -21232,6 +21244,30 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
|
||||
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
|
||||
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeEnhancement.kt")
|
||||
public void testTypeEnhancement() throws Exception {
|
||||
|
||||
@@ -285,7 +285,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
return this
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.doesFormSelfType(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
require(this is ConeTypeParameterLookupTag)
|
||||
return this.typeParameterSymbol.fir.bounds.any { typeRef ->
|
||||
typeRef.coneType.contains { it.typeConstructor() == this.getTypeConstructor() }
|
||||
|
||||
@@ -183,7 +183,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
||||
return false
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.doesFormSelfType(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
for (i in 0 until this.upperBoundCount()) {
|
||||
val upperBound = this.getUpperBound(i)
|
||||
if (upperBound.containsTypeConstructor(selfConstructor) && upperBound.typeConstructor() == selfConstructor) {
|
||||
|
||||
+1
-1
@@ -12,5 +12,5 @@ fun <R> choose3(c: Inv<Inv<R>>) {}
|
||||
fun f(o: Out<Out<*>>, i: In<In<*>>, inv: Inv<Inv<*>>) {
|
||||
choose1(o)
|
||||
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER{NI}, TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER{OI}!>choose2<!>(i)
|
||||
<!TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR{OI}!>choose3<!>(<!TYPE_MISMATCH{NI}!>inv<!>)
|
||||
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER{OI}, TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR{OI}!>choose3<!>(<!TYPE_MISMATCH!>inv<!>)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -28,5 +28,5 @@ abstract class MySettingsListener<S extends MyComparableSettings> {}
|
||||
fun test() {
|
||||
val a = MySettings.getSettings()
|
||||
a.getLinkedProjectsSettings()
|
||||
a.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE{OI}, TYPE_INFERENCE_UPPER_BOUND_VIOLATED{OI}, UNRESOLVED_REFERENCE_WRONG_RECEIVER{NI}!>linkedProjectsSettings<!>
|
||||
a.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE{OI}, TYPE_INFERENCE_UPPER_BOUND_VIOLATED{OI}!>linkedProjectsSettings<!>
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -10,5 +10,5 @@ public open class MySettings</*0*/ SS : MySettings<SS!, PS!, L!>!, /*1*/ PS : My
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun getSettings(): MySettings<(raw) MySettings<*, *, *>!, (raw) MyComparableSettings!, (raw) MySettingsListener<*>!>!
|
||||
public open fun getSettings(): (MySettings<(raw) *, (raw) MyComparableSettings!, (raw) MySettingsListener<MyComparableSettings!>!>..MySettings<*, *, out MySettingsListener<*>!>?)
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ package a {
|
||||
public open class C</*0*/ B : a.C<B!>!> {
|
||||
public constructor C</*0*/ B : a.C<B!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): a.C<(raw) a.C<*>!>!
|
||||
public open fun foo(): a.C<(raw) *>!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P, B>, P> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P, L> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // should be OK
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P, B>, P> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P, L> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<*, (kotlin.Any..kotlin.Any?)>..X<*, *>?)")!>t<!>
|
||||
t.id // should be OK
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I<P!, B!>!, /*1*/ P : kotlin.Any!> {
|
||||
public/*package*/ constructor X</*0*/ B : I<P!, B!>!, /*1*/ P : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<X<(raw) *, (raw) kotlin.Any!>!>!
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<B>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // should be OK
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<B>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<*>..X<*>?)")!>t<!>
|
||||
t.id // should be OK
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I<B!>!> {
|
||||
public/*package*/ constructor X</*0*/ B : I<B!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<X<(raw) *>!>!
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // should be OK
|
||||
}
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<(I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?), (kotlin.Any..kotlin.Any?)>..X<out (I<*>..I<*>?), *>?)")!>t<!>
|
||||
t.id // should be OK
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!> {
|
||||
public/*package*/ constructor X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<(X<(raw) I<kotlin.Any!>!, (raw) kotlin.Any!>..X<out I<*>!, *>?)>!
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I1<P, P, P>, P, A extends I1<I2<B>, B, I1<P, I2<B>, P>>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I1<P, A, F> {}
|
||||
interface I2<S> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // error before
|
||||
}
|
||||
compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I1<P, P, P>, P, A extends I1<I2<B>, B, I1<P, I2<B>, P>>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I1<P, A, F> {}
|
||||
interface I2<S> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<(I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>..I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>?), (kotlin.Any..kotlin.Any?), (I1<*, (I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>..I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>?), *>..I1<*, (I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>..I1<(kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?), (kotlin.Any..kotlin.Any?)>?), *>?)>..X<out (I1<*, *, *>..I1<*, *, *>?), *, out (I1<*, out (I1<*, *, *>..I1<*, *, *>?), *>..I1<*, out (I1<*, *, *>..I1<*, *, *>?), *>?)>?)")!>t<!>
|
||||
t.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>id<!> // error before
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I1<P!, P!, P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I1<I2<B!>!, B!, I1<P!, I2<B!>!, P!>!>!> {
|
||||
public/*package*/ constructor X</*0*/ B : I1<P!, P!, P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I1<I2<B!>!, B!, I1<P!, I2<B!>!, P!>!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<(X<(raw) I1<kotlin.Any!, kotlin.Any!, kotlin.Any!>!, (raw) kotlin.Any!, (raw) I1<*, I1<kotlin.Any!, kotlin.Any!, kotlin.Any!>!, *>!>..X<out I1<*, *, *>!, *, out I1<*, out I1<*, *, *>!, *>!>?)>!
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P, A extends I<B>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // should be OK
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P, A extends I<B>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<(I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?), (kotlin.Any..kotlin.Any?), (I<(I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?)>..I<(I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?)>?)>..X<out (I<*>..I<*>?), *, out (I<out (I<*>..I<*>?)>..I<out (I<*>..I<*>?)>?)>?)")!>t<!>
|
||||
t.id // should be OK
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I<B!>!> {
|
||||
public/*package*/ constructor X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I<B!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<(X<(raw) I<kotlin.Any!>!, (raw) kotlin.Any!, (raw) I<I<kotlin.Any!>!>!>..X<out I<*>!, *, out I<out I<*>!>!>?)>!
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P, A extends I<P>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.<!UNRESOLVED_REFERENCE!>t<!>
|
||||
t
|
||||
t.<!UNRESOLVED_REFERENCE!>id<!> // should be OK
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
|
||||
// FILE: X.java
|
||||
class X<B extends I<P>, P, A extends I<P>> {
|
||||
static final E<X> E = new E<>();
|
||||
|
||||
String getId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class E<T> {
|
||||
T getT() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface I<P> {}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test() {
|
||||
val t = X.E.t
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(X<(I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?), (kotlin.Any..kotlin.Any?), (I<(kotlin.Any..kotlin.Any?)>..I<(kotlin.Any..kotlin.Any?)>?)>..X<out (I<*>..I<*>?), *, out (I<*>..I<*>?)>?)")!>t<!>
|
||||
t.id // should be OK
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public/*package*/ open class X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I<P!>!> {
|
||||
public/*package*/ constructor X</*0*/ B : I<P!>!, /*1*/ P : kotlin.Any!, /*2*/ A : I<P!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun getId(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ final val E: E<(X<(raw) I<kotlin.Any!>!, (raw) kotlin.Any!, (raw) I<kotlin.Any!>!>..X<out I<*>!, *, out I<*>!>?)>!
|
||||
}
|
||||
Vendored
+2
-2
@@ -3,11 +3,11 @@ package test
|
||||
public open class RawSuperTypeWithRecursiveBound {
|
||||
public constructor RawSuperTypeWithRecursiveBound()
|
||||
|
||||
public open inner class Derived : test.RawSuperTypeWithRecursiveBound.Super<(raw) test.RawSuperTypeWithRecursiveBound.Super<*>!> {
|
||||
public open inner class Derived : test.RawSuperTypeWithRecursiveBound.Super<(raw) *> {
|
||||
public constructor Derived()
|
||||
public open override /*1*/ fun dummy(): kotlin.Unit
|
||||
public open fun foo(/*0*/ p0: kotlin.Any!): kotlin.Unit
|
||||
public open override /*1*/ fun foo(/*0*/ p0: test.RawSuperTypeWithRecursiveBound.Super<(raw) test.RawSuperTypeWithRecursiveBound.Super<*>!>!): kotlin.Unit
|
||||
public open override /*1*/ fun foo(/*0*/ p0: test.RawSuperTypeWithRecursiveBound.Super<(raw) *>!): kotlin.Unit
|
||||
}
|
||||
|
||||
public interface Super</*0*/ T : test.RawSuperTypeWithRecursiveBound.Super<T!>!> {
|
||||
|
||||
+2
-2
@@ -3,11 +3,11 @@ package test
|
||||
public open class RawSuperTypeWithRecursiveBoundMultipleParameters {
|
||||
public constructor RawSuperTypeWithRecursiveBoundMultipleParameters()
|
||||
|
||||
public open inner class Derived : test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>!> {
|
||||
public open inner class Derived : test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) *> {
|
||||
public constructor Derived()
|
||||
public open override /*1*/ fun dummy(): kotlin.Unit
|
||||
public open fun foo(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Any!): kotlin.Unit
|
||||
public open override /*1*/ fun foo(/*0*/ p0: kotlin.Any!, /*1*/ p1: test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>!>!): kotlin.Unit
|
||||
public open override /*1*/ fun foo(/*0*/ p0: kotlin.Any!, /*1*/ p1: test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) *>!): kotlin.Unit
|
||||
}
|
||||
|
||||
public interface Super</*0*/ R : kotlin.Any!, /*1*/ T : test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<R!, T!>!> {
|
||||
|
||||
Generated
+36
@@ -21148,6 +21148,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/arrays.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedRecursiveTypeArgumentAndNonRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt")
|
||||
public void testDontSubstituteAnotherErasedTypeArgumentIfRecursive() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/dontSubstituteAnotherErasedTypeArgumentIfRecursive.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("errorType.kt")
|
||||
public void testErrorType() throws Exception {
|
||||
@@ -21238,6 +21250,30 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/starProjectionToRaw.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteAnotherErasedTypeArgument.kt")
|
||||
public void testSubstituteAnotherErasedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteAnotherErasedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteOtherErasedDeepTypeArguments.kt")
|
||||
public void testSubstituteOtherErasedDeepTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteOtherErasedDeepTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedDependentTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedDependentTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedDependentTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("substituteSeveralOtherErasedTypeArguments.kt")
|
||||
public void testSubstituteSeveralOtherErasedTypeArguments() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeEnhancement.kt")
|
||||
public void testTypeEnhancement() throws Exception {
|
||||
|
||||
@@ -375,7 +375,7 @@ object AbstractTypeChecker {
|
||||
|
||||
val typeVariableConstructor = superArgumentType.typeConstructor() as? TypeVariableTypeConstructorMarker ?: return false
|
||||
|
||||
return typeVariableConstructor.typeParameter?.doesFormSelfType(selfConstructor) == true
|
||||
return typeVariableConstructor.typeParameter?.hasRecursiveBounds(selfConstructor) == true
|
||||
}
|
||||
|
||||
fun AbstractTypeCheckerContext.isSubtypeForSameConstructor(
|
||||
@@ -506,7 +506,7 @@ object AbstractTypeChecker {
|
||||
if (subType is CapturedTypeMarker) {
|
||||
val typeParameter =
|
||||
context.typeSystemContext.getTypeParameterForArgumentInBaseIfItEqualToTarget(baseType = superType, targetType = subType)
|
||||
if (typeParameter != null && typeParameter.doesFormSelfType(superType.typeConstructor())) {
|
||||
if (typeParameter != null && typeParameter.hasRecursiveBounds(superType.typeConstructor())) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
||||
fun TypeParameterMarker.upperBoundCount(): Int
|
||||
fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker
|
||||
fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker
|
||||
fun TypeParameterMarker.doesFormSelfType(selfConstructor: TypeConstructorMarker): Boolean
|
||||
fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean
|
||||
|
||||
fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean
|
||||
|
||||
|
||||
+46
-12
@@ -32,8 +32,7 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.Variance.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
private val JAVA_LANG_CLASS_FQ_NAME: FqName = FqName("java.lang.Class")
|
||||
@@ -210,6 +209,15 @@ class JavaTypeResolver(
|
||||
val typeParameters = constructor.parameters
|
||||
if (eraseTypeParameters) {
|
||||
return typeParameters.map { parameter ->
|
||||
/*
|
||||
* We shouldn't erase recursive type parameters to avoid creating types unsatisfying upper bounds.
|
||||
* E.g. if we got erased raw type of `class Foo<T: Foo<T>> {}` we'd create Foo<(raw) Foo<*>!>!,
|
||||
* but it's wrong because Foo<*> isn't subtype of Foo<Foo<*>> in accordance with declared upper bound of Foo.
|
||||
* So we should create Foo<*> in this case (CapturedType(*) is really subtype of Foo<CapturedType(*)>).
|
||||
*/
|
||||
if (hasTypeParameterRecursiveBounds(parameter, selfConstructor = null, attr.upperBoundOfTypeParameter))
|
||||
return@map StarProjectionImpl(parameter)
|
||||
|
||||
// Some activity for preventing recursion in cases like `class A<T extends A, F extends T>`
|
||||
//
|
||||
// When calculating upper bound of some parameter (attr.upperBoundOfTypeParameter),
|
||||
@@ -222,12 +230,11 @@ class JavaTypeResolver(
|
||||
// - Calculating second argument for raw upper bound of T. It depends on F, that again depends on upper bound of T,
|
||||
// so we get A<*, *>.
|
||||
// Summary result for upper bound of T is `A<A<*, *>, A<*, *>>..A<out A<*, *>, out A<*, *>>`
|
||||
val erasedUpperBound =
|
||||
LazyWrappedType(c.storageManager) {
|
||||
parameter.getErasedUpperBound(attr.upperBoundOfTypeParameter) {
|
||||
constructor.declarationDescriptor!!.defaultType.replaceArgumentsWithStarProjections()
|
||||
}
|
||||
val erasedUpperBound = LazyWrappedType(c.storageManager) {
|
||||
parameter.getErasedUpperBound(isRaw, attr) {
|
||||
constructor.declarationDescriptor!!.defaultType.replaceArgumentsWithStarProjections()
|
||||
}
|
||||
}
|
||||
|
||||
RawSubstitution.computeProjection(
|
||||
parameter,
|
||||
@@ -333,24 +340,51 @@ internal fun TypeParameterDescriptor.getErasedUpperBound(
|
||||
// Calculation of `potentiallyRecursiveTypeParameter.upperBounds` may recursively depend on `this.getErasedUpperBound`
|
||||
// E.g. `class A<T extends A, F extends A>`
|
||||
// To prevent recursive calls return defaultValue() instead
|
||||
potentiallyRecursiveTypeParameter: TypeParameterDescriptor? = null,
|
||||
isRaw: Boolean,
|
||||
typeAttr: JavaTypeAttributes,
|
||||
defaultValue: (() -> KotlinType) = { ErrorUtils.createErrorType("Can't compute erased upper bound of type parameter `$this`") }
|
||||
): KotlinType {
|
||||
if (this === potentiallyRecursiveTypeParameter) return defaultValue()
|
||||
if (this === typeAttr.upperBoundOfTypeParameter) return defaultValue()
|
||||
|
||||
/*
|
||||
* We should do erasure of containing type parameters with their erasure to avoid creating inconsistent types.
|
||||
* E.g. for `class Foo<T: Foo<B>, B>`, we'd have erasure for lower bound: Foo<Foo<*>, Any>,
|
||||
* but it's wrong type: projection(*) != projection(Any).
|
||||
* So we should substitute erasure of the corresponding type parameter: `Foo<Foo<Any>, Any>` or `Foo<Foo<*>, *>`.
|
||||
*/
|
||||
val erasedUpperBounds = defaultType.extractTypeParametersFromUpperBounds(typeAttr.upperBoundOfTypeParameter).associate {
|
||||
it.typeConstructor to RawSubstitution.computeProjection(
|
||||
this,
|
||||
// if erasure happens due to invalid arguments number, use star projections instead
|
||||
if (isRaw) typeAttr else typeAttr.withFlexibility(INFLEXIBLE),
|
||||
it.getErasedUpperBound(isRaw, typeAttr)
|
||||
)
|
||||
}
|
||||
val erasedUpperBoundsSubstitutor = TypeSubstitutor.create(TypeConstructorSubstitution.createByConstructorsMap(erasedUpperBounds))
|
||||
|
||||
val firstUpperBound = upperBounds.first()
|
||||
|
||||
if (firstUpperBound.constructor.declarationDescriptor is ClassDescriptor) {
|
||||
return firstUpperBound.replaceArgumentsWithStarProjections()
|
||||
return firstUpperBound.replaceArgumentsWithStarProjectionOrMapped(
|
||||
erasedUpperBoundsSubstitutor,
|
||||
erasedUpperBounds,
|
||||
OUT_VARIANCE,
|
||||
typeAttr.upperBoundOfTypeParameter
|
||||
)
|
||||
}
|
||||
|
||||
val stopAt = potentiallyRecursiveTypeParameter ?: this
|
||||
val stopAt = typeAttr.upperBoundOfTypeParameter ?: this
|
||||
var current = firstUpperBound.constructor.declarationDescriptor as TypeParameterDescriptor
|
||||
|
||||
while (current != stopAt) {
|
||||
val nextUpperBound = current.upperBounds.first()
|
||||
if (nextUpperBound.constructor.declarationDescriptor is ClassDescriptor) {
|
||||
return nextUpperBound.replaceArgumentsWithStarProjections()
|
||||
return nextUpperBound.replaceArgumentsWithStarProjectionOrMapped(
|
||||
erasedUpperBoundsSubstitutor,
|
||||
erasedUpperBounds,
|
||||
OUT_VARIANCE,
|
||||
typeAttr.upperBoundOfTypeParameter
|
||||
)
|
||||
}
|
||||
|
||||
current = nextUpperBound.constructor.declarationDescriptor as TypeParameterDescriptor
|
||||
|
||||
@@ -107,10 +107,9 @@ internal object RawSubstitution : TypeSubstitution() {
|
||||
private val lowerTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND)
|
||||
private val upperTypeAttr = TypeUsage.COMMON.toAttributes().withFlexibility(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND)
|
||||
|
||||
private fun eraseType(type: KotlinType): KotlinType {
|
||||
val declaration = type.constructor.declarationDescriptor
|
||||
return when (declaration) {
|
||||
is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound())
|
||||
private fun eraseType(type: KotlinType, attr: JavaTypeAttributes = JavaTypeAttributes(TypeUsage.COMMON)): KotlinType {
|
||||
return when (val declaration = type.constructor.declarationDescriptor) {
|
||||
is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound(isRaw = true, attr), attr)
|
||||
is ClassDescriptor -> {
|
||||
val declarationForUpper =
|
||||
type.upperIfFlexible().constructor.declarationDescriptor
|
||||
@@ -142,7 +141,7 @@ internal object RawSubstitution : TypeSubstitution() {
|
||||
if (KotlinBuiltIns.isArray(type)) {
|
||||
val componentTypeProjection = type.arguments[0]
|
||||
val arguments = listOf(
|
||||
TypeProjectionImpl(componentTypeProjection.projectionKind, eraseType(componentTypeProjection.type))
|
||||
TypeProjectionImpl(componentTypeProjection.projectionKind, eraseType(componentTypeProjection.type, attr))
|
||||
)
|
||||
return KotlinTypeFactory.simpleType(
|
||||
type.annotations, type.constructor, arguments, type.isMarkedNullable
|
||||
@@ -171,7 +170,7 @@ internal object RawSubstitution : TypeSubstitution() {
|
||||
fun computeProjection(
|
||||
parameter: TypeParameterDescriptor,
|
||||
attr: JavaTypeAttributes,
|
||||
erasedUpperBound: KotlinType = parameter.getErasedUpperBound()
|
||||
erasedUpperBound: KotlinType = parameter.getErasedUpperBound(isRaw = true, attr)
|
||||
) = when (attr.flexibility) {
|
||||
// Raw(List<T>) => (List<Any?>..List<*>)
|
||||
// Raw(Enum<T>) => (Enum<Enum<*>>..Enum<out Enum<*>>)
|
||||
|
||||
@@ -185,7 +185,74 @@ fun KotlinType.contains(predicate: (UnwrappedType) -> Boolean) = TypeUtils.conta
|
||||
fun KotlinType.replaceArgumentsWithStarProjections() = replaceArgumentsWith(::StarProjectionImpl)
|
||||
fun KotlinType.replaceArgumentsWithNothing() = replaceArgumentsWith { it.builtIns.nothingType.asTypeProjection() }
|
||||
|
||||
private inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): KotlinType {
|
||||
fun KotlinType.extractTypeParametersFromUpperBounds(upperBoundOfTypeParameter: TypeParameterDescriptor?): Set<TypeParameterDescriptor> =
|
||||
mutableSetOf<TypeParameterDescriptor>().also { extractTypeParametersFromUpperBounds(this, it, upperBoundOfTypeParameter) }
|
||||
|
||||
private fun KotlinType.extractTypeParametersFromUpperBounds(
|
||||
baseType: KotlinType,
|
||||
to: MutableSet<TypeParameterDescriptor>,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
) {
|
||||
val declarationDescriptor = constructor.declarationDescriptor
|
||||
|
||||
if (declarationDescriptor is TypeParameterDescriptor) {
|
||||
if (constructor != baseType.constructor) {
|
||||
to += declarationDescriptor
|
||||
} else {
|
||||
for (upperBound in declarationDescriptor.upperBounds) {
|
||||
upperBound.extractTypeParametersFromUpperBounds(baseType, to, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val typeParameters = (constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters
|
||||
for ((i, argument) in arguments.withIndex()) {
|
||||
val typeParameter = typeParameters?.get(i)
|
||||
if (argument.isStarProjection || (typeParameter != null && typeParameter == upperBoundOfTypeParameter)) continue
|
||||
if (argument.type.constructor.declarationDescriptor in to || argument.type.constructor == baseType.constructor) continue
|
||||
argument.type.extractTypeParametersFromUpperBounds(baseType, to, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun hasTypeParameterRecursiveBounds(
|
||||
typeParameter: TypeParameterDescriptor,
|
||||
selfConstructor: TypeConstructor? = null,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor? = null
|
||||
): Boolean =
|
||||
typeParameter.upperBounds.any { upperBound ->
|
||||
upperBound.containsSelfTypeParameter(typeParameter.defaultType.constructor, upperBoundOfTypeParameter)
|
||||
&& (selfConstructor == null || upperBound.constructor == selfConstructor)
|
||||
}
|
||||
|
||||
private fun KotlinType.containsSelfTypeParameter(
|
||||
baseConstructor: TypeConstructor,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
): Boolean {
|
||||
if (this.constructor == baseConstructor) return true
|
||||
|
||||
val typeParameters = (constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters
|
||||
return arguments.withIndex().any { (i, argument) ->
|
||||
val typeParameter = typeParameters?.get(i)
|
||||
if ((typeParameter != null && typeParameter == upperBoundOfTypeParameter) || argument.isStarProjection) return@any false
|
||||
argument.type.containsSelfTypeParameter(baseConstructor, upperBoundOfTypeParameter)
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinType.replaceArgumentsWithStarProjectionOrMapped(
|
||||
substitutor: TypeSubstitutor,
|
||||
substitutionMap: Map<TypeConstructor, TypeProjection>,
|
||||
variance: Variance,
|
||||
upperBoundOfTypeParameter: TypeParameterDescriptor?
|
||||
) =
|
||||
replaceArgumentsWith { typeParameterDescriptor ->
|
||||
val argument = arguments.getOrNull(typeParameterDescriptor.index)
|
||||
if (typeParameterDescriptor != upperBoundOfTypeParameter && argument != null && argument.type.constructor in substitutionMap) {
|
||||
argument
|
||||
} else StarProjectionImpl(typeParameterDescriptor)
|
||||
}.let { substitutor.safeSubstitute(it, variance) }
|
||||
|
||||
|
||||
inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): KotlinType {
|
||||
val unwrapped = unwrap()
|
||||
return when (unwrapped) {
|
||||
is FlexibleType -> KotlinTypeFactory.flexibleType(
|
||||
@@ -196,7 +263,7 @@ private inline fun KotlinType.replaceArgumentsWith(replacement: (TypeParameterDe
|
||||
}.inheritEnhancement(unwrapped)
|
||||
}
|
||||
|
||||
private inline fun SimpleType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): SimpleType {
|
||||
inline fun SimpleType.replaceArgumentsWith(replacement: (TypeParameterDescriptor) -> TypeProjection): SimpleType {
|
||||
if (constructor.parameters.isEmpty() || constructor.declarationDescriptor == null) return this
|
||||
|
||||
val newArguments = constructor.parameters.map(replacement)
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.hasTypeParameterRecursiveBounds
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
||||
@@ -220,11 +221,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return this.typeConstructor
|
||||
}
|
||||
|
||||
override fun TypeParameterMarker.doesFormSelfType(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean {
|
||||
require(this is TypeParameterDescriptor, this::errorMessage)
|
||||
require(selfConstructor is TypeConstructor, this::errorMessage)
|
||||
|
||||
return doesTypeParameterFormSelfType(this, selfConstructor)
|
||||
return hasTypeParameterRecursiveBounds(this, selfConstructor)
|
||||
}
|
||||
|
||||
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||
import java.util.*
|
||||
|
||||
@@ -106,8 +105,3 @@ private fun TypeConstructor.debugInfo() = buildString {
|
||||
interface NewTypeVariableConstructor {
|
||||
val originalTypeParameter: TypeParameterDescriptor?
|
||||
}
|
||||
|
||||
fun doesTypeParameterFormSelfType(typeParameter: TypeParameterDescriptor, selfConstructor: TypeConstructor) =
|
||||
typeParameter.upperBounds.any { upperBound ->
|
||||
upperBound.contains { it.constructor == typeParameter.typeConstructor } && upperBound.constructor == selfConstructor
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user