[NI] Fix type intersection for equal types

This commit is contained in:
Mikhail Zarechenskiy
2017-07-03 10:48:20 +03:00
parent ac507e721c
commit cf75afba66
6 changed files with 62 additions and 5 deletions
@@ -0,0 +1,18 @@
// WITH_RUNTIME
// FILE: test.kt
fun foo() {
takeClass(run {
val outer: Sample<out Any>? = null
if (outer != null) outer else null
})
}
fun takeClass(instanceClass: Sample<*>?) {}
class Sample<T : Any>
fun box(): String {
foo()
return "OK"
}
@@ -16580,6 +16580,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("intersectionOfEqualTypes.kt")
public void testIntersectionOfEqualTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt");
doTest(fileName);
}
@TestMetadata("kt10143.kt")
public void testKt10143() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/kt10143.kt");
@@ -16580,6 +16580,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("intersectionOfEqualTypes.kt")
public void testIntersectionOfEqualTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt");
doTest(fileName);
}
@TestMetadata("kt10143.kt")
public void testKt10143() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/kt10143.kt");
@@ -16580,6 +16580,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("intersectionOfEqualTypes.kt")
public void testIntersectionOfEqualTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt");
doTest(fileName);
}
@TestMetadata("kt10143.kt")
public void testKt10143() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/kt10143.kt");
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -99,22 +99,37 @@ object TypeIntersector {
// nullability here is correct
private fun intersectTypesWithoutIntersectionType(inputTypes: Set<SimpleType>): SimpleType {
if (inputTypes.size == 1) return inputTypes.single()
// Any and Nothing should leave
// Note that duplicates should be dropped because we have Set here.
val filteredSupertypes = inputTypes.filterNot { upper ->
inputTypes.any { upper != it && NewKotlinTypeChecker.isSubtypeOf(it, upper) }
val filteredSuperAndEqualTypes = ArrayList(inputTypes)
val iterator = filteredSuperAndEqualTypes.iterator()
while (iterator.hasNext()) {
val upper = iterator.next()
val strictSupertypeOrHasEqual = filteredSuperAndEqualTypes.any { lower ->
lower !== upper && (isStrictSupertype(lower, upper) || NewKotlinTypeChecker.equalTypes(lower, upper))
}
if (strictSupertypeOrHasEqual) iterator.remove()
}
assert(filteredSupertypes.isNotEmpty()) {
assert(filteredSuperAndEqualTypes.isNotEmpty()) {
"This collections cannot be empty! input types: ${inputTypes.joinToString()}"
}
if (filteredSupertypes.size < 2) return filteredSupertypes.single()
if (filteredSuperAndEqualTypes.size < 2) return filteredSuperAndEqualTypes.single()
val constructor = IntersectionTypeConstructor(inputTypes)
return KotlinTypeFactory.simpleType(Annotations.EMPTY, constructor, listOf(), false, constructor.createScopeForKotlinType())
}
private fun isStrictSupertype(subtype: KotlinType, supertype: KotlinType): Boolean {
return with(NewKotlinTypeChecker) {
isSubtypeOf(subtype, supertype) && !isSubtypeOf(supertype, subtype)
}
}
/**
* Let T is type parameter with upper bound Any?. resultNullability(String? & T) = UNKNOWN => String? & T
*/
@@ -20234,6 +20234,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("intersectionOfEqualTypes.kt")
public void testIntersectionOfEqualTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt");
doTest(fileName);
}
@TestMetadata("kt10143.kt")
public void testKt10143() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/regressions/kt10143.kt");