[NI] Use projected type for constraint like Cap(out A) <: out @Exact T
This is an implicit semantics of Exact annotation
This commit is contained in:
+18
-2
@@ -57,8 +57,10 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact()
|
val hasExact = subType.isTypeVariableWithExact() || superType.isTypeVariableWithExact()
|
||||||
|
|
||||||
// we should strip annotation's because we have incorporation operation and they should be not affected
|
// we should strip annotation's because we have incorporation operation and they should be not affected
|
||||||
val mySubType = if (hasExact) subType.removeExactAnnotation() else subType
|
val mySubType =
|
||||||
val mySuperType = if (hasExact) superType.removeExactAnnotation() else superType
|
if (hasExact) extractTypeForProjectedType(subType, out = true) ?: subType.removeExactAnnotation() else subType
|
||||||
|
val mySuperType =
|
||||||
|
if (hasExact) extractTypeForProjectedType(superType, out = false) ?: superType.removeExactAnnotation() else superType
|
||||||
|
|
||||||
val result = internalAddSubtypeConstraint(mySubType, mySuperType)
|
val result = internalAddSubtypeConstraint(mySubType, mySuperType)
|
||||||
if (!hasExact) return result
|
if (!hasExact) return result
|
||||||
@@ -69,6 +71,20 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
return (result ?: true) && (result2 ?: true)
|
return (result ?: true) && (result2 ?: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun extractTypeForProjectedType(type: KotlinTypeMarker, out: Boolean): KotlinTypeMarker? {
|
||||||
|
val typeMarker = type.asSimpleType()?.asCapturedType() ?: return null
|
||||||
|
|
||||||
|
val projection = typeMarker.typeConstructorProjection()
|
||||||
|
if (projection.isStarProjection()) return null
|
||||||
|
|
||||||
|
|
||||||
|
return when (projection.getVariance()) {
|
||||||
|
TypeVariance.IN -> if (!out) typeMarker.lowerType() ?: projection.getType() else null
|
||||||
|
TypeVariance.OUT -> if (out) projection.getType() else null
|
||||||
|
TypeVariance.INV -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KotlinTypeMarker.isTypeVariableWithExact() =
|
private fun KotlinTypeMarker.isTypeVariableWithExact() =
|
||||||
hasExactAnnotation() && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
hasExactAnnotation() && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// KJS_WITH_FULL_RUNTIME
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class ValByMapExtensionsTest {
|
||||||
|
val map: Map<String, String> = hashMapOf("a" to "all", "b" to "bar", "c" to "code")
|
||||||
|
val genericMap = mapOf<String, Any?>("i" to 1, "x" to 1.0)
|
||||||
|
val mmapOut: MutableMap<String, out String> = mutableMapOf("g" to "out", "g1" to "in")
|
||||||
|
val genericMmapOut: MutableMap<String, out Any?> = mmapOut
|
||||||
|
|
||||||
|
val a by map
|
||||||
|
val b: String by map
|
||||||
|
val c: Any by map
|
||||||
|
val d: String? by map
|
||||||
|
val e: String by map.withDefault { "default" }
|
||||||
|
val f: String? by map.withDefault { null }
|
||||||
|
val g: String by mmapOut
|
||||||
|
val g1: String by genericMmapOut
|
||||||
|
|
||||||
|
val i: Int by genericMap
|
||||||
|
val x: Double by genericMap
|
||||||
|
|
||||||
|
fun doTest() {
|
||||||
|
assertEquals("all", a)
|
||||||
|
assertEquals("bar", b)
|
||||||
|
assertEquals("code", c)
|
||||||
|
assertEquals("default", e)
|
||||||
|
assertEquals(null, f)
|
||||||
|
assertEquals("out", g)
|
||||||
|
assertEquals("in", g1)
|
||||||
|
assertEquals(1, i)
|
||||||
|
assertEquals(1.0, x)
|
||||||
|
assertFailsWith<NoSuchElementException> { d }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
ValByMapExtensionsTest().doTest()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -9849,6 +9849,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
+5
@@ -9849,6 +9849,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
+5
@@ -8724,6 +8724,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
+5
@@ -8724,6 +8724,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
Generated
+5
@@ -7479,6 +7479,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
+5
@@ -7479,6 +7479,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/useReflectionOnKProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valByMapDelegatedProperty.kt")
|
||||||
|
public void testValByMapDelegatedProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/delegatedProperty/valByMapDelegatedProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valInInnerClass.kt")
|
@TestMetadata("valInInnerClass.kt")
|
||||||
public void testValInInnerClass() throws Exception {
|
public void testValInInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
runTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user