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:
+15
@@ -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
|
||||
}
|
||||
}
|
||||
+19
@@ -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
|
||||
}
|
||||
+16
@@ -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
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user