From b3c5760eb5260e25644b32f3859a00e612d94709 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 21 Jan 2016 15:41:45 +0300 Subject: [PATCH] Type intersection fix: T & (final A) is no more calculated as just A #KT-7801 Fixed --- .../kotlin/types/TypeIntersector.java | 22 ++++++++++++------- .../tests/generics/nullability/smartCasts.kt | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java b/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java index 027a0f524fc..e94950cc1da 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java @@ -78,21 +78,27 @@ public class TypeIntersector { outer: for (KotlinType type : nullabilityStripped) { if (!TypeUtils.canHaveSubtypes(typeChecker, type)) { + boolean relativeToAll = true; for (KotlinType other : nullabilityStripped) { // It makes sense to check for subtyping (other <: type), despite that // type is not supposed to be open, for there're enums - if (!TypeUnifier.mayBeEqual(type, other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) { + boolean mayBeEqual = TypeUnifier.mayBeEqual(type, other); + boolean relative = typeChecker.isSubtypeOf(type, other) || typeChecker.isSubtypeOf(other, type); + if (!mayBeEqual && !relative) { return null; } - } - return TypeUtils.makeNullableAsSpecified(type, allNullable); - } - else { - for (KotlinType other : nullabilityStripped) { - if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) { - continue outer; + else if (!relative) { + // To build T & (final A), instead of returning just A as intersection + relativeToAll = false; + break; } } + if (relativeToAll) return TypeUtils.makeNullableAsSpecified(type, allNullable); + } + for (KotlinType other : nullabilityStripped) { + if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) { + continue outer; + } } // Don't add type if it is already present, to avoid trivial type intersections in result diff --git a/compiler/testData/diagnostics/tests/generics/nullability/smartCasts.kt b/compiler/testData/diagnostics/tests/generics/nullability/smartCasts.kt index af429a2a70c..cb3ab821ee7 100644 --- a/compiler/testData/diagnostics/tests/generics/nullability/smartCasts.kt +++ b/compiler/testData/diagnostics/tests/generics/nullability/smartCasts.kt @@ -29,7 +29,7 @@ fun foo(x: T) { x.length x?.length - x.bar1() + x.bar1() x.bar2() x.bar3() }