Filtering error types and accounting for platform types when computing intersections
KT-6508 Build impossible because of NoSuchElementException #KT-6508 Fixed
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
// !EXPLICIT_FLEXIBLE_TYPES
|
||||
|
||||
fun foo(
|
||||
p1: ft<MutableMap<Int, String>, Map<Int, String>?>,
|
||||
p2: Map<Int, String>
|
||||
) = p1 == p2
|
||||
|
||||
fun foo(
|
||||
p1: ft<String, String?>,
|
||||
p2: String
|
||||
) = p1 == p2
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ p1: kotlin.(Mutable)Map<kotlin.Int, kotlin.String>!, /*1*/ p2: kotlin.Map<kotlin.Int, kotlin.String>): kotlin.Boolean
|
||||
internal fun foo(/*0*/ p1: kotlin.String!, /*1*/ p2: kotlin.String): kotlin.Boolean
|
||||
@@ -0,0 +1,24 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION
|
||||
|
||||
// FILE: foo/View.java
|
||||
|
||||
package foo;
|
||||
|
||||
public class View {}
|
||||
|
||||
// FILE: foo/TextView.java
|
||||
|
||||
package foo;
|
||||
|
||||
public class TextView extends View {}
|
||||
|
||||
// FILE: k.kt
|
||||
|
||||
import foo.View
|
||||
//import foo.TextView
|
||||
|
||||
fun String.gah(view:View ?) {
|
||||
if (view is <!UNRESOLVED_REFERENCE!>TextView<!>)
|
||||
<!DEBUG_INFO_SMARTCAST!>view<!>
|
||||
else <!UNRESOLVED_REFERENCE!>TextView<!>() as foo.TextView
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun kotlin.String.gah(/*0*/ view: foo.View?): kotlin.Unit
|
||||
@@ -8043,7 +8043,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/platformTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({PlatformTypes.CommonSupertype.class, PlatformTypes.MethodCall.class})
|
||||
@InnerTestClasses({PlatformTypes.CommonSupertype.class, PlatformTypes.Intersection.class, PlatformTypes.MethodCall.class})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PlatformTypes extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInPlatformTypes() throws Exception {
|
||||
@@ -8185,6 +8185,21 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/platformTypes/intersection")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Intersection extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInIntersection() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/intersection"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("map.kt")
|
||||
public void testMap() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/intersection/map.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/platformTypes/methodCall")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -8953,6 +8968,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6508.kt")
|
||||
public void testKt6508() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/kt6508.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt688.kt")
|
||||
public void testKt688() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/kt688.kt");
|
||||
|
||||
@@ -30,6 +30,8 @@ public class IntersectionTypeConstructor extends AnnotatedImpl implements TypeCo
|
||||
|
||||
public IntersectionTypeConstructor(Annotations annotations, Collection<JetType> typesToIntersect) {
|
||||
super(annotations);
|
||||
assert !typesToIntersect.isEmpty() : "Attempt to create an empty intersection";
|
||||
|
||||
this.intersectedTypes = new LinkedHashSet<JetType>(typesToIntersect);
|
||||
this.hashCode = intersectedTypes.hashCode();
|
||||
}
|
||||
|
||||
@@ -172,6 +172,8 @@ public class TypeUtils {
|
||||
boolean nothingTypePresent = false;
|
||||
List<JetType> nullabilityStripped = new ArrayList<JetType>(types.size());
|
||||
for (JetType type : types) {
|
||||
if (type.isError()) continue;
|
||||
|
||||
nothingTypePresent |= KotlinBuiltIns.isNothingOrNullableNothing(type);
|
||||
allNullable &= type.isMarkedNullable();
|
||||
nullabilityStripped.add(makeNotNullable(type));
|
||||
@@ -181,6 +183,11 @@ public class TypeUtils {
|
||||
return allNullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType();
|
||||
}
|
||||
|
||||
if (nullabilityStripped.isEmpty()) {
|
||||
// All types were errors
|
||||
return ErrorUtils.createErrorType("Intersection of errors types: " + types);
|
||||
}
|
||||
|
||||
// Now we remove types that have subtypes in the list
|
||||
List<JetType> resultingTypes = new ArrayList<JetType>();
|
||||
outer:
|
||||
@@ -213,11 +220,23 @@ public class TypeUtils {
|
||||
resultingTypes.add(type);
|
||||
}
|
||||
|
||||
if (resultingTypes.isEmpty()) {
|
||||
// If we ended up here, it means that all types from `nullabilityStripped` were excluded by the code above
|
||||
// most likely, this is because they are all semantically interchangeable (e.g. List<Foo>! and List<Foo>),
|
||||
// in that case, we can safely select the best representative out of that set and return it
|
||||
// TODO: maybe return the most specific among the types that are subtypes to all others in the `nullabilityStripped`?
|
||||
// TODO: e.g. among {Int, Int?, Int!}, return `Int` (now it returns `Int!`).
|
||||
JetType bestRepresentative = TypesPackage.singleBestRepresentative(nullabilityStripped);
|
||||
if (bestRepresentative == null) {
|
||||
throw new AssertionError("Empty intersection for types " + types);
|
||||
}
|
||||
return makeNullableAsSpecified(bestRepresentative, allNullable);
|
||||
}
|
||||
|
||||
if (resultingTypes.size() == 1) {
|
||||
return makeNullableAsSpecified(resultingTypes.get(0), allNullable);
|
||||
}
|
||||
|
||||
|
||||
TypeConstructor constructor = new IntersectionTypeConstructor(Annotations.EMPTY, resultingTypes);
|
||||
|
||||
JetScope[] scopes = new JetScope[resultingTypes.size()];
|
||||
|
||||
@@ -67,7 +67,7 @@ public fun JetType.isNullabilityFlexible(): Boolean {
|
||||
}
|
||||
|
||||
// This function is intended primarily for sets: since JetType.equals() represents _syntactical_ equality of types,
|
||||
// whereas JetTypeChecker.DEFAULT.equalsTypes() represents semantical equality
|
||||
// whereas JetTypeChecker.DEFAULT.equalsTypes() represents semantic equality
|
||||
// A set of types (e.g. exact bounds etc) may contain, for example, X, X? and X!
|
||||
// These are not equal syntactically (by JetType.equals()), but X! is _compatible_ with others as exact bounds,
|
||||
// moreover, X! is a better fit.
|
||||
|
||||
Reference in New Issue
Block a user