Fix concrete method inheritance in interfaces

For each non-abstract non-declared (i.e. inherited from supertypes) method in
an interface we generate its static form to the TImpl, which calls the TImpl
method from the corresponding supertype.

The accidental override tests changed because we're now trying to generate the
delegate for the super method, not knowing that it will clash with the declared
method

 #KT-2888 Fixed
 #KT-5393 Fixed
This commit is contained in:
Alexander Udalov
2014-07-25 17:41:01 +04:00
parent f81c364999
commit 4dcc373a5a
32 changed files with 441 additions and 65 deletions
@@ -16,11 +16,12 @@
package org.jetbrains.kotlin.backend.common.bridges
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.OverrideResolver
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil
import org.jetbrains.kotlin.types.TypeUtils
public fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor,
@@ -64,36 +65,50 @@ private data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescrip
/**
* Given a fake override in a class, returns an overridden declaration with implementation in trait, such that a method delegating to that
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
* override of any trait implementation or such method was already generated into some superclass
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
*/
public fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
if (descriptor.getKind().isReal()) return null
if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null
// TODO: this logic is quite common for bridge generation, find a way to abstract it to a single place
// TODO: don't use filterOutOverridden() here, it's an internal front-end utility (see its implementation)
val overriddenDeclarations = OverrideResolver.getOverriddenDeclarations(descriptor)
val filteredOverriddenDeclarations = OverrideResolver.filterOutOverridden(overriddenDeclarations)
val implementation = findImplementationFromInterface(descriptor) ?: return null
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
var implementation: CallableMemberDescriptor? = null
for (overriddenDeclaration in filteredOverriddenDeclarations) {
if (DescriptorUtils.isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) {
implementation = overriddenDeclaration
}
}
if (implementation == null) {
if (!DescriptorUtils.isTrait(immediateConcreteSuper.getContainingDeclaration())) {
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
return null
}
// If this implementation is already generated into one of the superclasses, we need not generate it again, it'll be inherited
val containingClass = descriptor.getContainingDeclaration() as ClassDescriptor
val implClassType = implementation!!.getDispatchReceiverParameter()!!.getType()
for (supertype in containingClass.getDefaultType().getConstructor().getSupertypes()) {
if (!DescriptorUtils.isTrait(supertype.getConstructor().getDeclarationDescriptor()!!) &&
TypeUtils.getAllSupertypes(supertype).contains(implClassType)) {
return null
}
}
return implementation
return immediateConcreteSuper
}
/**
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
* that should be called when the given fake override is called.
*/
public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
val filtered = OverrideResolver.filterOutOverridden(overridden)
val result = filtered.firstOrNull { it.getModality() != Modality.ABSTRACT } ?: return null
val container = result.getContainingDeclaration()
if (DescriptorUtils.isClass(container) || DescriptorUtils.isEnumClass(container)) return null
return result
}
/**
* Given a fake override and its implementation (non-abstract declaration) somewhere in supertypes,
* returns the first immediate super function of the given fake override which overrides that implementation.
* The returned function should be called from TImpl-bridges generated for the given fake override.
*/
public fun firstSuperMethodFromKotlin(
descriptor: CallableMemberDescriptor,
implementation: CallableMemberDescriptor
): CallableMemberDescriptor? {
return descriptor.getOverriddenDescriptors().firstOrNull { overridden ->
overridden.getModality() != Modality.ABSTRACT &&
(overridden == implementation || OverrideResolver.overrides(overridden, implementation))
}
}
@@ -21,15 +21,27 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
import org.jetbrains.kotlin.psi.JetClassOrObject;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Iterator;
import java.util.List;
import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.findImplementationFromInterface;
import static org.jetbrains.kotlin.backend.common.bridges.BridgesPackage.firstSuperMethodFromKotlin;
import static org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class TraitImplBodyCodegen extends ClassBodyCodegen {
public TraitImplBodyCodegen(
@NotNull JetClassOrObject aClass,
@NotNull ClassContext context,
@@ -52,6 +64,91 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
v.visitSource(myClass.getContainingFile().getName(), null);
}
@Override
protected void generateSyntheticParts() {
for (DeclarationDescriptor memberDescriptor : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (!(memberDescriptor instanceof CallableMemberDescriptor)) continue;
CallableMemberDescriptor fakeOverride = (CallableMemberDescriptor) memberDescriptor;
if (fakeOverride.getKind().isReal()) continue;
if (fakeOverride.getVisibility() == Visibilities.INVISIBLE_FAKE) continue;
if (fakeOverride.getModality() == Modality.ABSTRACT) continue;
CallableMemberDescriptor implementation = findImplementationFromInterface(fakeOverride);
if (implementation == null) continue;
// If implementation is located in a Java interface, it will be inherited via normal Java rules
if (implementation instanceof JavaMethodDescriptor) continue;
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
CallableMemberDescriptor copy = fakeOverride.copy(
fakeOverride.getContainingDeclaration(), Modality.OPEN, fakeOverride.getVisibility(),
CallableMemberDescriptor.Kind.DECLARATION, true
);
if (fakeOverride instanceof FunctionDescriptor) {
generateDelegationToSuperTraitImpl((FunctionDescriptor) copy, (FunctionDescriptor) implementation);
}
else if (fakeOverride instanceof PropertyDescriptor) {
PropertyGetterDescriptor getter = ((PropertyDescriptor) copy).getGetter();
PropertyGetterDescriptor implGetter = ((PropertyDescriptor) implementation).getGetter();
if (getter != null && implGetter != null) {
generateDelegationToSuperTraitImpl(getter, implGetter);
}
PropertySetterDescriptor setter = ((PropertyDescriptor) copy).getSetter();
PropertySetterDescriptor implSetter = ((PropertyDescriptor) implementation).getSetter();
if (setter != null && implSetter != null) {
generateDelegationToSuperTraitImpl(setter, implSetter);
}
}
}
}
private void generateDelegationToSuperTraitImpl(@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor implementation) {
final FunctionDescriptor delegateTo = (FunctionDescriptor) firstSuperMethodFromKotlin(descriptor, implementation);
if (delegateTo == null) return;
// We can't call super methods from Java 1.8 interfaces because that requires INVOKESPECIAL which is forbidden from TImpl class
if (delegateTo instanceof JavaMethodDescriptor) return;
functionCodegen.generateMethod(
DiagnosticsPackage.DelegationToTraitImpl(descriptorToDeclaration(descriptor), descriptor),
descriptor,
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, descriptor) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
InstructionAdapter iv = codegen.v;
CallableMethod method = typeMapper.mapToCallableMethod(delegateTo, true, context);
List<JvmMethodParameterSignature> myParameters = signature.getValueParameters();
List<JvmMethodParameterSignature> calleeParameters = method.getValueParameters();
if (myParameters.size() != calleeParameters.size()) {
throw new AssertionError(
String.format(
"Method from super interface has a different signature.\n" +
"This method:\n%s\n%s\n%s\nSuper method:\n%s\n%s\n%s",
callableDescriptor, signature, myParameters, delegateTo, method, calleeParameters
)
);
}
int k = 0;
Iterator<JvmMethodParameterSignature> it = calleeParameters.iterator();
for (JvmMethodParameterSignature parameter : myParameters) {
Type type = parameter.getAsmType();
StackValue.local(k, type).put(it.next().getAsmType(), iv);
k += type.getSize();
}
method.genInvokeInstruction(iv);
StackValue.coerce(method.getReturnType(), signature.getReturnType(), iv);
iv.areturn(signature.getReturnType());
}
}
);
}
@Override
protected void generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor)
@@ -578,7 +578,7 @@ public class JetTypeMapper {
}
else {
invokeOpcode = INVOKESTATIC;
signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
signature = mapSignature(descriptor.getOriginal(), OwnerKind.TRAIT_IMPL);
owner = mapTraitImpl(currentOwner);
}
}
@@ -77,6 +77,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
doTestWithJava(fileName);
}
@TestMetadata("longChainOfKotlinExtendsFromJavaWithDefault")
public void testLongChainOfKotlinExtendsFromJavaWithDefault() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/");
doTestWithJava(fileName);
}
@TestMetadata("samOnInterfaceWithDefaultMethod")
public void testSamOnInterfaceWithDefaultMethod() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/samOnInterfaceWithDefaultMethod/");
+17
View File
@@ -0,0 +1,17 @@
interface A {
fun foo(): String {
return "OK"
}
}
interface B : A
class C : B {
override fun foo(): String {
return super.foo()
}
}
fun box(): String {
return C().foo()
}
+20
View File
@@ -0,0 +1,20 @@
var result = "Fail"
interface A {
var foo: String
get() = result
set(value) { result = value }
}
interface B : A
class C : B {
override var foo: String
get() = super.foo
set(value) { super.foo = value }
}
fun box(): String {
C().foo = "OK"
return C().foo
}
+15
View File
@@ -0,0 +1,15 @@
interface A {
override fun toString(): String {
return "OK"
}
}
interface B : A
class C : B {
override fun toString(): String {
return super.toString()
}
}
fun box() = "${C()}"
@@ -0,0 +1,18 @@
interface A {
fun foo(): Number {
return 42
}
}
interface B : A
class C : B {
override fun foo(): Int {
return super.foo() as Int
}
}
fun box(): String {
val x = C().foo()
return if (x == 42) "OK" else "Fail: $x"
}
@@ -0,0 +1,15 @@
interface A {
fun foo() = "Fail"
}
interface B : A
interface C : A {
override fun foo() = "OK"
}
interface D : B, C
class Impl : D
fun box(): String = Impl().foo()
@@ -0,0 +1,18 @@
interface A<T, U : Number, V : Any> {
fun foo(t: T, u: U): V? {
return null
}
}
interface B<T, V : Any> : A<T, Int, V>
class C : B<String, Runnable> {
override fun foo(t: String, u: Int): Runnable? {
return super.foo(t, u)
}
}
fun box(): String {
val x = C().foo("", 0)
return if (x == null) "OK" else "Fail: $x"
}
@@ -0,0 +1,3 @@
interface A {
void foo();
}
@@ -0,0 +1,16 @@
interface B : A {
fun bar() = 1
}
interface C : B
class D : C {
override fun foo() {}
}
fun box(): String {
val d = D()
d.foo()
d.bar()
return "OK"
}
@@ -0,0 +1,13 @@
interface A {
fun foo(): String
}
interface B {
fun foo(): String = "OK"
}
interface C : A, B
// There's no 'foo' in A$$TImpl, proguard and other tools may fail if we generate calls to it
// 0 INVOKESTATIC A\$\$TImpl.foo
// 1 INVOKESTATIC B\$\$TImpl.foo
@@ -0,0 +1,15 @@
// If we generate equals/hashCode/toString in all interfaces, there will be too much bytecode
interface A {
fun foo(): Number = 42
}
interface B : A
class C : B {
override fun foo(): Int = super.foo() as Int
}
// 0 equals
// 0 hashCode
// 0 toString
@@ -0,0 +1,5 @@
public interface Base {
default String foo() {
return "OK";
}
}
@@ -0,0 +1,11 @@
interface K1 : Base
interface K2 : K1
interface K3 : K2
class C : K3 {
override fun foo() = super.foo()
}
fun box(): String = C().foo()
@@ -1,8 +0,0 @@
interface T {
fun getX() = 1
}
interface C : T {
val x: Int
<!ACCIDENTAL_OVERRIDE!>get()<!> = 1
}
@@ -1,8 +0,0 @@
interface T {
val x: Int
get() = 1
}
interface C : T {
<!ACCIDENTAL_OVERRIDE!>fun getX()<!> = 1
}
@@ -0,0 +1,8 @@
interface T {
fun getX() = 1
}
interface <!CONFLICTING_JVM_DECLARATIONS!>C<!> : T {
val x: Int
get() = 1
}
@@ -0,0 +1,8 @@
interface T {
val x: Int
get() = 1
}
interface <!CONFLICTING_JVM_DECLARATIONS!>C<!> : T {
fun getX() = 1
}
@@ -4328,12 +4328,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt")
public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyInTrait.kt");
doTest(fileName);
}
@TestMetadata("traitFunctionOverriddenByPropertyNoImpl.kt")
public void testTraitFunctionOverriddenByPropertyNoImpl() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyNoImpl.kt");
@@ -4346,12 +4340,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt")
public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionInTrait.kt");
doTest(fileName);
}
@TestMetadata("traitPropertyOverriddenByFunctionNoImpl.kt")
public void testTraitPropertyOverriddenByFunctionNoImpl() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionNoImpl.kt");
@@ -4712,6 +4700,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("traitFunctionOverriddenByPropertyInTrait.kt")
public void testTraitFunctionOverriddenByPropertyInTrait() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitFunctionOverriddenByPropertyInTrait.kt");
doTest(fileName);
}
@TestMetadata("traitPropertyOverriddenByFunctionInTrait.kt")
public void testTraitPropertyOverriddenByFunctionInTrait() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/traitPropertyOverriddenByFunctionInTrait.kt");
doTest(fileName);
}
@TestMetadata("twoTraits.kt")
public void testTwoTraits() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/twoTraits.kt");
@@ -215,12 +215,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("traitImplGeneratedOnce.kt")
public void testTraitImplGeneratedOnce() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -512,6 +506,33 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/interfaces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Interfaces extends AbstractBytecodeTextTest {
public void testAllFilesPresentInInterfaces() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/interfaces"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("firstInheritedMethodIsAbstract.kt")
public void testFirstInheritedMethodIsAbstract() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/firstInheritedMethodIsAbstract.kt");
doTest(fileName);
}
@TestMetadata("noAnyMethodsOnInterfaceInheritance.kt")
public void testNoAnyMethodsOnInterfaceInheritance() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/noAnyMethodsOnInterfaceInheritance.kt");
doTest(fileName);
}
@TestMetadata("traitImplGeneratedOnce.kt")
public void testTraitImplGeneratedOnce() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaces/traitImplGeneratedOnce.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/lazyCodegen")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -395,6 +395,21 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/interfaces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Interfaces extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInInterfaces() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/interfaces"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("inheritJavaInterface.kt")
public void testInheritJavaInterface() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/interfaces/inheritJavaInterface.kt");
doTestAgainstJava(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -7045,6 +7045,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("kt5393.kt")
public void testKt5393() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393.kt");
doTest(fileName);
}
@TestMetadata("kt5393_property.kt")
public void testKt5393_property() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_property.kt");
doTest(fileName);
}
@TestMetadata("kt5393_toString.kt")
public void testKt5393_toString() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5393_toString.kt");
doTest(fileName);
}
@TestMetadata("kt5495.kt")
public void testKt5495() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5495.kt");
@@ -7057,6 +7075,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("traitImplDelegationWithCovariantOverride.kt")
public void testTraitImplDelegationWithCovariantOverride() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt");
doTest(fileName);
}
@TestMetadata("traitImplDiamond.kt")
public void testTraitImplDiamond() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDiamond.kt");
doTest(fileName);
}
@TestMetadata("traitImplGenericDelegation.kt")
public void testTraitImplGenericDelegation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplGenericDelegation.kt");
doTest(fileName);
}
@TestMetadata("traitWithPrivateExtension.kt")
public void testTraitWithPrivateExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitWithPrivateExtension.kt");
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
public interface PropertyAccessorDescriptor extends FunctionDescriptor {
boolean hasBody();
@@ -27,6 +29,10 @@ public interface PropertyAccessorDescriptor extends FunctionDescriptor {
@Override
PropertyAccessorDescriptor getOriginal();
@Override
@NotNull
Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors();
@NotNull
PropertyDescriptor getCorrespondingProperty();
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
public interface PropertyGetterDescriptor extends PropertyAccessorDescriptor {
@NotNull
@Override
PropertyGetterDescriptor getOriginal();
@Override
@NotNull
Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors();
}
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
public interface PropertySetterDescriptor extends PropertyAccessorDescriptor {
@NotNull
@Override
PropertySetterDescriptor getOriginal();
@Override
@NotNull
Set<? extends PropertySetterDescriptor> getOverriddenDescriptors();
}
@@ -56,8 +56,9 @@ public class PropertyGetterDescriptorImpl extends PropertyAccessorDescriptorImpl
@NotNull
@Override
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
return super.getOverriddenDescriptors(true);
@SuppressWarnings("unchecked")
public Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors() {
return (Set) super.getOverriddenDescriptors(true);
}
@NotNull
@@ -72,8 +72,9 @@ public class PropertySetterDescriptorImpl extends PropertyAccessorDescriptorImpl
@NotNull
@Override
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
return super.getOverriddenDescriptors(false);
@SuppressWarnings("unchecked")
public Set<? extends PropertySetterDescriptor> getOverriddenDescriptors() {
return (Set) super.getOverriddenDescriptors(false);
}
@NotNull