Refine 'isMoreSpecific' calculation

Choose member with better visibility, it's needed for proper calculation
of types intersection member scope

 #KT-10481 Fixed
This commit is contained in:
Denis Zharkov
2016-02-02 11:40:25 +03:00
parent 148b53fc62
commit 8df05c6c4c
6 changed files with 100 additions and 0 deletions
@@ -0,0 +1,15 @@
open class A {
open var value: Int = 4
protected set
}
class MutableA : A() {
override var value: Int = 4
public set
}
fun test(myA: A) {
if (myA is MutableA) {
<!DEBUG_INFO_SMARTCAST!>myA<!>.value = 5
}
}
@@ -0,0 +1,19 @@
package
public fun test(/*0*/ myA: A): kotlin.Unit
public open class A {
public constructor A()
public open var value: kotlin.Int
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 MutableA : A {
public constructor MutableA()
public open override /*1*/ var value: kotlin.Int
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
}
@@ -0,0 +1,16 @@
abstract class A {
abstract protected fun foo(): String
abstract protected val bar: String
}
interface B {
fun foo(): String
val bar: String
}
fun test(x: A) {
if (x is B) {
<!DEBUG_INFO_SMARTCAST!>x<!>.foo()
<!DEBUG_INFO_SMARTCAST!>x<!>.bar
}
}
@@ -0,0 +1,20 @@
package
public fun test(/*0*/ x: A): kotlin.Unit
public abstract class A {
public constructor A()
protected abstract val bar: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected abstract fun foo(): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public abstract val bar: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -16538,6 +16538,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("moreSpecificSetter.kt")
public void testMoreSpecificSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/intersectionScope/moreSpecificSetter.kt");
doTest(fileName);
}
@TestMetadata("moreSpecificVisibility.kt")
public void testMoreSpecificVisibility() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/intersectionScope/moreSpecificVisibility.kt");
doTest(fileName);
}
@TestMetadata("mostSpecific.kt")
public void testMostSpecific() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/intersectionScope/mostSpecific.kt");
@@ -338,6 +338,8 @@ public class OverridingUtil {
assert aReturnType != null : "Return type of " + a + " is null";
assert bReturnType != null : "Return type of " + b + " is null";
if (!isVisibilityMoreSpecific(a, b)) return false;
if (a instanceof SimpleFunctionDescriptor) {
assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
@@ -348,6 +350,9 @@ public class OverridingUtil {
PropertyDescriptor pa = (PropertyDescriptor) a;
PropertyDescriptor pb = (PropertyDescriptor) b;
if (!isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false;
if (pa.isVar() && pb.isVar()) {
return DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters()).equalTypes(aReturnType, bReturnType);
}
@@ -359,6 +364,19 @@ public class OverridingUtil {
throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
}
private static boolean isVisibilityMoreSpecific(
@NotNull DeclarationDescriptorWithVisibility a,
@NotNull DeclarationDescriptorWithVisibility b
) {
Integer result = Visibilities.compare(a.getVisibility(), b.getVisibility());
return result == null || result >= 0;
}
private static boolean isAccessorMoreSpecific(@Nullable PropertyAccessorDescriptor a, @Nullable PropertyAccessorDescriptor b) {
if (a == null || b == null) return true;
return isVisibilityMoreSpecific(a, b);
}
private static boolean isMoreSpecificThenAllOf(@NotNull CallableDescriptor candidate, @NotNull Collection<CallableDescriptor> descriptors) {
// NB subtyping relation in Kotlin is not transitive in presence of flexible types:
// String? <: String! <: String, but not String? <: String