FIR synthetics: make setter subtype check more precise #KT-43347 Fixed

This commit is contained in:
Mikhail Glukhikh
2020-12-24 16:02:38 +03:00
parent 8c8f81330a
commit 0d40fde713
8 changed files with 95 additions and 22 deletions
@@ -1873,6 +1873,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
runTest("compiler/testData/ir/irText/firProblems/SignatureClash.kt");
}
@TestMetadata("SyntheticSetterType.kt")
public void testSyntheticSetterType() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/SyntheticSetterType.kt");
}
@TestMetadata("throwableStackTrace.kt")
public void testThrowableStackTrace() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/throwableStackTrace.kt");
@@ -80,28 +80,22 @@ class FirSyntheticPropertiesScope(
val parameter = setter.valueParameters.singleOrNull() ?: return
if (setter.typeParameters.isNotEmpty() || setter.isStatic) return
val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.type ?: return
if (getter.symbol.dispatchReceiverClassOrNull() == setter.symbol.dispatchReceiverClassOrNull()) {
if (getterReturnType.withNullability(NOT_NULL) != parameterType.withNullability(NOT_NULL)) {
return
}
} else {
// TODO: at this moment it works for cases like
// class Base {
// void setSomething(Object value) {}
// }
// class Derived extends Base {
// String getSomething() { return ""; }
// }
// In FE 1.0, we should have also Object getSomething() in class Base for this to work
// I think details here are worth designing
if (!AbstractTypeChecker.isSubtypeOf(
session.typeContext,
getterReturnType.withNullability(NOT_NULL),
parameterType.withNullability(NOT_NULL)
)
) {
return
}
// TODO: at this moment it works for cases like
// class Base {
// void setSomething(Object value) {}
// }
// class Derived extends Base {
// String getSomething() { return ""; }
// }
// In FE 1.0, we should have also Object getSomething() in class Base for this to work
// I think details here are worth designing
if (!AbstractTypeChecker.isSubtypeOf(
session.typeContext,
getterReturnType.withNullability(NOT_NULL),
parameterType.withNullability(NOT_NULL)
)
) {
return
}
matchingSetter = setter
})
@@ -0,0 +1,3 @@
fun foo(descriptor: PropertyDescriptorImpl) {
descriptor.setOverriddenDescriptors(overriddenDescriptors = emptyList<PropertyDescriptor?>())
}
@@ -0,0 +1,8 @@
FILE fqName:<root> fileName:/SyntheticSetterType.kt
FUN name:foo visibility:public modality:FINAL <> (descriptor:<root>.PropertyDescriptorImpl) returnType:kotlin.Unit
VALUE_PARAMETER name:descriptor index:0 type:<root>.PropertyDescriptorImpl
BLOCK_BODY
CALL 'public open fun setOverriddenDescriptors (overriddenDescriptors: @[EnhancedNullability] kotlin.collections.Collection<out <root>.CallableMemberDescriptor?>): kotlin.Unit declared in <root>.PropertyDescriptorImpl' type=kotlin.Unit origin=EQ
$this: GET_VAR 'descriptor: <root>.PropertyDescriptorImpl declared in <root>.foo' type=<root>.PropertyDescriptorImpl origin=null
overriddenDescriptors: CALL 'public final fun emptyList <T> (): kotlin.collections.List<T of kotlin.collections.emptyList> declared in kotlin.collections' type=kotlin.collections.List<<root>.PropertyDescriptor?> origin=null
<T>: <root>.PropertyDescriptor?
@@ -0,0 +1,47 @@
// WITH_RUNTIME
// FILE: PropertyDescriptorImpl.java
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class PropertyDescriptorImpl implements PropertyDescriptor {
@Override
public void setOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors) {
this.overriddenProperties = (Collection<? extends PropertyDescriptor>) overriddenDescriptors;
}
@NotNull
@Override
public Collection<? extends PropertyDescriptor> getOverriddenDescriptors() {
return overriddenProperties != null ? overriddenProperties : Collections.<PropertyDescriptor>emptyList();
}
}
// FILE: PropertyDescriptor.java
import org.jetbrains.annotations.NotNull;
import java.util.*;
public interface PropertyDescriptor extends CallableMemberDescriptor {
@NotNull
@Override
Collection<? extends PropertyDescriptor> getOverriddenDescriptors();
}
// FILE: CallableMemberDescriptor.java
import org.jetbrains.annotations.NotNull;
import java.util.*;
public interface CallableMemberDescriptor {
@NotNull
Collection<? extends CallableMemberDescriptor> getOverriddenDescriptors();
void setOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors);
}
// FILE: SyntheticSetterType.kt
fun foo(descriptor: PropertyDescriptorImpl) {
descriptor.overriddenDescriptors = emptyList()
}
@@ -0,0 +1,3 @@
fun foo(descriptor: PropertyDescriptorImpl) {
descriptor.setOverriddenDescriptors(overriddenDescriptors = emptyList<@FlexibleNullability PropertyDescriptor?>())
}
@@ -0,0 +1,8 @@
FILE fqName:<root> fileName:/SyntheticSetterType.kt
FUN name:foo visibility:public modality:FINAL <> (descriptor:<root>.PropertyDescriptorImpl) returnType:kotlin.Unit
VALUE_PARAMETER name:descriptor index:0 type:<root>.PropertyDescriptorImpl
BLOCK_BODY
CALL 'public open fun setOverriddenDescriptors (overriddenDescriptors: @[EnhancedNullability] kotlin.collections.MutableCollection<out @[FlexibleNullability] <root>.CallableMemberDescriptor?>): kotlin.Unit declared in <root>.PropertyDescriptorImpl' type=kotlin.Unit origin=EQ
$this: GET_VAR 'descriptor: <root>.PropertyDescriptorImpl declared in <root>.foo' type=<root>.PropertyDescriptorImpl origin=null
overriddenDescriptors: CALL 'public final fun emptyList <T> (): kotlin.collections.List<T of kotlin.collections.emptyList> declared in kotlin.collections' type=kotlin.collections.List<@[FlexibleNullability] <root>.PropertyDescriptor?> origin=null
<T>: @[FlexibleNullability] <root>.PropertyDescriptor?
@@ -1872,6 +1872,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
runTest("compiler/testData/ir/irText/firProblems/SignatureClash.kt");
}
@TestMetadata("SyntheticSetterType.kt")
public void testSyntheticSetterType() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/SyntheticSetterType.kt");
}
@TestMetadata("throwableStackTrace.kt")
public void testThrowableStackTrace() throws Exception {
runTest("compiler/testData/ir/irText/firProblems/throwableStackTrace.kt");