[NI] Properly support UnsafeVariance annotation
#KT-38134 Fixed #KT-34433 Fixed #KT-31823 Fixed
This commit is contained in:
+15
@@ -9154,11 +9154,26 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceInAliasedFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceInAliasedFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceOnInputTypeOfFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceOnInputTypeOfFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceOnInputTypeOfFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceStar.kt")
|
@TestMetadata("unsafeVarianceStar.kt")
|
||||||
public void testUnsafeVarianceStar() throws Exception {
|
public void testUnsafeVarianceStar() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceWithRecursiveGenerics.kt")
|
||||||
|
public void testUnsafeVarianceWithRecursiveGenerics() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceWithRecursiveGenerics.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("varargs.kt")
|
@TestMetadata("varargs.kt")
|
||||||
public void testVarargs() throws Exception {
|
public void testVarargs() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
||||||
|
|||||||
Generated
+5
@@ -12105,6 +12105,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class A<out K> {
|
||||||
|
fun foo(x: @UnsafeVariance K): K = x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(a: A<*>): Any? {
|
||||||
|
return a.foo("OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(A<String>()) as String
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
|
class Foo<out T>(val baz: Baz<T>)
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
val foo: Foo<*> = TODO()
|
||||||
|
|
||||||
|
fun <T> bar(): Baz<T> {
|
||||||
|
return foo.baz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias Baz<T> = (@UnsafeVariance T) -> Unit
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class Bar {
|
||||||
|
public constructor Bar()
|
||||||
|
public final val foo: Foo<*>
|
||||||
|
public final fun </*0*/ T> bar(): Baz<T> /* = (@kotlin.UnsafeVariance T) -> kotlin.Unit */
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ out T> {
|
||||||
|
public constructor Foo</*0*/ out T>(/*0*/ baz: Baz<T> /* = (@kotlin.UnsafeVariance T) -> kotlin.Unit */)
|
||||||
|
public final val baz: Baz<T> /* = (@kotlin.UnsafeVariance T) -> kotlin.Unit */
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
public typealias Baz</*0*/ T> = (@kotlin.UnsafeVariance T) -> kotlin.Unit
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -REDUNDANT_PROJECTION
|
||||||
|
|
||||||
|
class FunctionHolder<out T : Any>(val f: (@UnsafeVariance T) -> Unit) {
|
||||||
|
fun f2(v: @UnsafeVariance T) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun caller(
|
||||||
|
holder1: FunctionHolder<out Any>,
|
||||||
|
holder2: FunctionHolder<*>,
|
||||||
|
holder3: FunctionHolder<Any>,
|
||||||
|
a: Any
|
||||||
|
) {
|
||||||
|
holder1.f(a)
|
||||||
|
holder1.f2(a)
|
||||||
|
|
||||||
|
holder2.f(a)
|
||||||
|
holder2.f2(a)
|
||||||
|
|
||||||
|
holder3.f(a)
|
||||||
|
holder3.f2(a)
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun caller(/*0*/ holder1: FunctionHolder<out kotlin.Any>, /*1*/ holder2: FunctionHolder<*>, /*2*/ holder3: FunctionHolder<kotlin.Any>, /*3*/ a: kotlin.Any): kotlin.Unit
|
||||||
|
|
||||||
|
public final class FunctionHolder</*0*/ out T : kotlin.Any> {
|
||||||
|
public constructor FunctionHolder</*0*/ out T : kotlin.Any>(/*0*/ f: (@kotlin.UnsafeVariance T) -> kotlin.Unit)
|
||||||
|
public final val f: (@kotlin.UnsafeVariance T) -> kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun f2(/*0*/ v: @kotlin.UnsafeVariance T): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
|
||||||
|
|
||||||
interface A<out K> {
|
|
||||||
fun foo(x: @UnsafeVariance K): Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test(a: A<*>) {
|
|
||||||
a.foo(null)
|
|
||||||
a.foo(Any())
|
|
||||||
}
|
|
||||||
+3
-3
@@ -1,10 +1,10 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
interface A<out K> {
|
interface A<out K> {
|
||||||
fun foo(x: @UnsafeVariance K): Unit
|
fun foo(x: @UnsafeVariance K): Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test(a: A<*>) {
|
fun test(a: A<*>) {
|
||||||
a.foo(<!NI;NULL_FOR_NONNULL_TYPE!>null<!>)
|
a.foo(null)
|
||||||
a.foo(<!NI;TYPE_MISMATCH!>Any()<!>)
|
a.foo(Any())
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
interface UpdatableRendering<out T : UpdatableRendering<T>> {
|
||||||
|
fun canUpdateFrom(another: @UnsafeVariance T): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Any.matchesRendering(other: Any): Boolean {
|
||||||
|
return when {
|
||||||
|
this::class != other::class -> false
|
||||||
|
this !is UpdatableRendering<*> -> true
|
||||||
|
else -> this.<!INAPPLICABLE_CANDIDATE!>canUpdateFrom<!>(other as UpdatableRendering<*>)
|
||||||
|
}
|
||||||
|
}
|
||||||
compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceWithRecursiveGenerics.kt
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
interface UpdatableRendering<out T : UpdatableRendering<T>> {
|
||||||
|
fun canUpdateFrom(another: @UnsafeVariance T): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Any.matchesRendering(other: Any): Boolean {
|
||||||
|
return when {
|
||||||
|
this::class != other::class -> false
|
||||||
|
this !is UpdatableRendering<*> -> true
|
||||||
|
else -> <!DEBUG_INFO_SMARTCAST!>this<!>.canUpdateFrom(other as UpdatableRendering<*>)
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun kotlin.Any.matchesRendering(/*0*/ other: kotlin.Any): kotlin.Boolean
|
||||||
|
|
||||||
|
public interface UpdatableRendering</*0*/ out T : UpdatableRendering<T>> {
|
||||||
|
public abstract fun canUpdateFrom(/*0*/ another: @kotlin.UnsafeVariance T): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -9161,11 +9161,26 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceInAliasedFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceInAliasedFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceOnInputTypeOfFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceOnInputTypeOfFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceOnInputTypeOfFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceStar.kt")
|
@TestMetadata("unsafeVarianceStar.kt")
|
||||||
public void testUnsafeVarianceStar() throws Exception {
|
public void testUnsafeVarianceStar() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceWithRecursiveGenerics.kt")
|
||||||
|
public void testUnsafeVarianceWithRecursiveGenerics() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceWithRecursiveGenerics.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("varargs.kt")
|
@TestMetadata("varargs.kt")
|
||||||
public void testVarargs() throws Exception {
|
public void testVarargs() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
||||||
|
|||||||
Generated
+15
@@ -9156,11 +9156,26 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceInAliasedFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceInAliasedFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceInAliasedFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceOnInputTypeOfFunctionalType.kt")
|
||||||
|
public void testUnsafeVarianceOnInputTypeOfFunctionalType() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceOnInputTypeOfFunctionalType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unsafeVarianceStar.kt")
|
@TestMetadata("unsafeVarianceStar.kt")
|
||||||
public void testUnsafeVarianceStar() throws Exception {
|
public void testUnsafeVarianceStar() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceWithRecursiveGenerics.kt")
|
||||||
|
public void testUnsafeVarianceWithRecursiveGenerics() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceWithRecursiveGenerics.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("varargs.kt")
|
@TestMetadata("varargs.kt")
|
||||||
public void testVarargs() throws Exception {
|
public void testVarargs() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
runTest("compiler/testData/diagnostics/tests/generics/projectionsScope/varargs.kt");
|
||||||
|
|||||||
+5
@@ -13320,6 +13320,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -13320,6 +13320,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -12105,6 +12105,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations;
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations;
|
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt;
|
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorKt;
|
||||||
|
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor;
|
||||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker;
|
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker;
|
||||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
||||||
@@ -91,7 +92,7 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return unsafeSubstitute(new TypeProjectionImpl(howThisTypeIsUsed, type), 0).getType();
|
return unsafeSubstitute(new TypeProjectionImpl(howThisTypeIsUsed, type), null, 0).getType();
|
||||||
} catch (SubstitutionException e) {
|
} catch (SubstitutionException e) {
|
||||||
return ErrorUtils.createErrorType(e.getMessage());
|
return ErrorUtils.createErrorType(e.getMessage());
|
||||||
}
|
}
|
||||||
@@ -121,14 +122,18 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return unsafeSubstitute(typeProjection, 0);
|
return unsafeSubstitute(typeProjection, null, 0);
|
||||||
} catch (SubstitutionException e) {
|
} catch (SubstitutionException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TypeProjection unsafeSubstitute(@NotNull TypeProjection originalProjection, int recursionDepth) throws SubstitutionException {
|
private TypeProjection unsafeSubstitute(
|
||||||
|
@NotNull TypeProjection originalProjection,
|
||||||
|
@Nullable TypeParameterDescriptor typeParameter,
|
||||||
|
int recursionDepth
|
||||||
|
) throws SubstitutionException {
|
||||||
assertRecursionDepth(recursionDepth, originalProjection, substitution);
|
assertRecursionDepth(recursionDepth, originalProjection, substitution);
|
||||||
|
|
||||||
if (originalProjection.isStarProjection()) return originalProjection;
|
if (originalProjection.isStarProjection()) return originalProjection;
|
||||||
@@ -141,6 +146,7 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
|
|
||||||
TypeProjection substitution = unsafeSubstitute(
|
TypeProjection substitution = unsafeSubstitute(
|
||||||
new TypeProjectionImpl(originalProjection.getProjectionKind(), origin),
|
new TypeProjectionImpl(originalProjection.getProjectionKind(), origin),
|
||||||
|
typeParameter,
|
||||||
recursionDepth + 1
|
recursionDepth + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -154,14 +160,27 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
return originalProjection; // todo investigate
|
return originalProjection; // todo investigate
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeProjection replacement = substitution.get(type);
|
TypeProjection substituted = substitution.get(type);
|
||||||
|
TypeProjection replacement =
|
||||||
|
substituted != null ?
|
||||||
|
projectedTypeForConflictedTypeWithUnsafeVariance(type, substituted, typeParameter, originalProjection) :
|
||||||
|
null;
|
||||||
|
|
||||||
Variance originalProjectionKind = originalProjection.getProjectionKind();
|
Variance originalProjectionKind = originalProjection.getProjectionKind();
|
||||||
if (replacement == null && FlexibleTypesKt.isFlexible(type) && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
|
if (replacement == null && FlexibleTypesKt.isFlexible(type) && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
|
||||||
FlexibleType flexibleType = FlexibleTypesKt.asFlexibleType(type);
|
FlexibleType flexibleType = FlexibleTypesKt.asFlexibleType(type);
|
||||||
TypeProjection substitutedLower =
|
TypeProjection substitutedLower =
|
||||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getLowerBound()), recursionDepth + 1);
|
unsafeSubstitute(
|
||||||
|
new TypeProjectionImpl(originalProjectionKind, flexibleType.getLowerBound()),
|
||||||
|
typeParameter,
|
||||||
|
recursionDepth + 1
|
||||||
|
);
|
||||||
TypeProjection substitutedUpper =
|
TypeProjection substitutedUpper =
|
||||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getUpperBound()), recursionDepth + 1);
|
unsafeSubstitute(
|
||||||
|
new TypeProjectionImpl(originalProjectionKind, flexibleType.getUpperBound()),
|
||||||
|
typeParameter,
|
||||||
|
recursionDepth + 1
|
||||||
|
);
|
||||||
|
|
||||||
Variance substitutedProjectionKind = substitutedLower.getProjectionKind();
|
Variance substitutedProjectionKind = substitutedLower.getProjectionKind();
|
||||||
assert (substitutedProjectionKind == substitutedUpper.getProjectionKind()) &&
|
assert (substitutedProjectionKind == substitutedUpper.getProjectionKind()) &&
|
||||||
@@ -225,6 +244,37 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
return substituteCompoundType(originalProjection, recursionDepth);
|
return substituteCompoundType(originalProjection, recursionDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static TypeProjection projectedTypeForConflictedTypeWithUnsafeVariance(
|
||||||
|
@NotNull KotlinType originalType,
|
||||||
|
@NotNull TypeProjection substituted,
|
||||||
|
@Nullable TypeParameterDescriptor typeParameter,
|
||||||
|
@NotNull TypeProjection originalProjection
|
||||||
|
) {
|
||||||
|
if (!originalType.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.unsafeVariance)) return substituted;
|
||||||
|
|
||||||
|
TypeConstructor constructor = substituted.getType().getConstructor();
|
||||||
|
if (!(constructor instanceof NewCapturedTypeConstructor)) return substituted;
|
||||||
|
|
||||||
|
NewCapturedTypeConstructor capturedType = (NewCapturedTypeConstructor) constructor;
|
||||||
|
TypeProjection capturedTypeProjection = capturedType.getProjection();
|
||||||
|
Variance varianceOfCapturedType = capturedTypeProjection.getProjectionKind();
|
||||||
|
|
||||||
|
VarianceConflictType conflictWithTopLevelType = conflictType(originalProjection.getProjectionKind(), varianceOfCapturedType);
|
||||||
|
if (conflictWithTopLevelType == VarianceConflictType.OUT_IN_IN_POSITION) {
|
||||||
|
return new TypeProjectionImpl(capturedTypeProjection.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeParameter == null) return substituted;
|
||||||
|
|
||||||
|
VarianceConflictType conflictTypeWithTypeParameter = conflictType(typeParameter.getVariance(), varianceOfCapturedType);
|
||||||
|
if (conflictTypeWithTypeParameter == VarianceConflictType.OUT_IN_IN_POSITION) {
|
||||||
|
return new TypeProjectionImpl(capturedTypeProjection.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return substituted;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static Annotations filterOutUnsafeVariance(@NotNull Annotations annotations) {
|
private static Annotations filterOutUnsafeVariance(@NotNull Annotations annotations) {
|
||||||
if (!annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.unsafeVariance)) return annotations;
|
if (!annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.unsafeVariance)) return annotations;
|
||||||
@@ -275,7 +325,7 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
|
|||||||
TypeParameterDescriptor typeParameter = typeParameters.get(i);
|
TypeParameterDescriptor typeParameter = typeParameters.get(i);
|
||||||
TypeProjection typeArgument = typeArguments.get(i);
|
TypeProjection typeArgument = typeArguments.get(i);
|
||||||
|
|
||||||
TypeProjection substitutedTypeArgument = unsafeSubstitute(typeArgument, recursionDepth + 1);
|
TypeProjection substitutedTypeArgument = unsafeSubstitute(typeArgument, typeParameter, recursionDepth + 1);
|
||||||
|
|
||||||
switch (conflictType(typeParameter.getVariance(), substitutedTypeArgument.getProjectionKind())) {
|
switch (conflictType(typeParameter.getVariance(), substitutedTypeArgument.getProjectionKind())) {
|
||||||
case NO_CONFLICT:
|
case NO_CONFLICT:
|
||||||
|
|||||||
Generated
+5
@@ -10385,6 +10385,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -10450,6 +10450,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unsafeVarianceCodegen.kt")
|
||||||
|
public void testUnsafeVarianceCodegen() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
Reference in New Issue
Block a user