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:
@@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.bridges
|
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.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil
|
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
|
||||||
|
|
||||||
public fun <Signature> generateBridgesForFunctionDescriptor(
|
public fun <Signature> generateBridgesForFunctionDescriptor(
|
||||||
descriptor: FunctionDescriptor,
|
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
|
* 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
|
* 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? {
|
public fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||||
if (descriptor.getKind().isReal()) return null
|
if (descriptor.getKind().isReal()) return null
|
||||||
if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) 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
|
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
||||||
// TODO: don't use filterOutOverridden() here, it's an internal front-end utility (see its implementation)
|
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
||||||
val overriddenDeclarations = OverrideResolver.getOverriddenDeclarations(descriptor)
|
|
||||||
val filteredOverriddenDeclarations = OverrideResolver.filterOutOverridden(overriddenDeclarations)
|
|
||||||
|
|
||||||
var implementation: CallableMemberDescriptor? = null
|
if (!DescriptorUtils.isTrait(immediateConcreteSuper.getContainingDeclaration())) {
|
||||||
for (overriddenDeclaration in filteredOverriddenDeclarations) {
|
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
||||||
if (DescriptorUtils.isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) {
|
|
||||||
implementation = overriddenDeclaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (implementation == null) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this implementation is already generated into one of the superclasses, we need not generate it again, it'll be inherited
|
return immediateConcreteSuper
|
||||||
val containingClass = descriptor.getContainingDeclaration() as ClassDescriptor
|
}
|
||||||
val implClassType = implementation!!.getDispatchReceiverParameter()!!.getType()
|
|
||||||
for (supertype in containingClass.getDefaultType().getConstructor().getSupertypes()) {
|
/**
|
||||||
if (!DescriptorUtils.isTrait(supertype.getConstructor().getDeclarationDescriptor()!!) &&
|
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
||||||
TypeUtils.getAllSupertypes(supertype).contains(implClassType)) {
|
* that should be called when the given fake override is called.
|
||||||
return null
|
*/
|
||||||
}
|
public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||||
}
|
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
|
||||||
|
val filtered = OverrideResolver.filterOutOverridden(overridden)
|
||||||
return implementation
|
|
||||||
|
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.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
import org.jetbrains.kotlin.codegen.context.ClassContext;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
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.psi.JetClassOrObject;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
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.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
|
||||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
|
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.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||||
|
|
||||||
public TraitImplBodyCodegen(
|
public TraitImplBodyCodegen(
|
||||||
@NotNull JetClassOrObject aClass,
|
@NotNull JetClassOrObject aClass,
|
||||||
@NotNull ClassContext context,
|
@NotNull ClassContext context,
|
||||||
@@ -52,6 +64,91 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
|||||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
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
|
@Override
|
||||||
protected void generateKotlinAnnotation() {
|
protected void generateKotlinAnnotation() {
|
||||||
writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor)
|
writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor)
|
||||||
|
|||||||
@@ -578,7 +578,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
invokeOpcode = INVOKESTATIC;
|
invokeOpcode = INVOKESTATIC;
|
||||||
signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
|
signature = mapSignature(descriptor.getOriginal(), OwnerKind.TRAIT_IMPL);
|
||||||
owner = mapTraitImpl(currentOwner);
|
owner = mapTraitImpl(currentOwner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -77,6 +77,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
|||||||
doTestWithJava(fileName);
|
doTestWithJava(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("longChainOfKotlinExtendsFromJavaWithDefault")
|
||||||
|
public void testLongChainOfKotlinExtendsFromJavaWithDefault() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/longChainOfKotlinExtendsFromJavaWithDefault/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("samOnInterfaceWithDefaultMethod")
|
@TestMetadata("samOnInterfaceWithDefaultMethod")
|
||||||
public void testSamOnInterfaceWithDefaultMethod() throws Exception {
|
public void testSamOnInterfaceWithDefaultMethod() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/samOnInterfaceWithDefaultMethod/");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/java8/boxWithJava/samOnInterfaceWithDefaultMethod/");
|
||||||
|
|||||||
+17
@@ -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()
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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()}"
|
||||||
+18
@@ -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"
|
||||||
|
}
|
||||||
+13
@@ -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
|
||||||
+15
@@ -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
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
public interface Base {
|
||||||
|
default String foo() {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+11
@@ -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()
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
interface T {
|
|
||||||
fun getX() = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
interface C : T {
|
|
||||||
val x: Int
|
|
||||||
<!ACCIDENTAL_OVERRIDE!>get()<!> = 1
|
|
||||||
}
|
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
interface T {
|
|
||||||
val x: Int
|
|
||||||
get() = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
interface C : T {
|
|
||||||
<!ACCIDENTAL_OVERRIDE!>fun getX()<!> = 1
|
|
||||||
}
|
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
interface T {
|
||||||
|
fun getX() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
interface <!CONFLICTING_JVM_DECLARATIONS!>C<!> : T {
|
||||||
|
val x: Int
|
||||||
|
get() = 1
|
||||||
|
}
|
||||||
+8
@@ -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);
|
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")
|
@TestMetadata("traitFunctionOverriddenByPropertyNoImpl.kt")
|
||||||
public void testTraitFunctionOverriddenByPropertyNoImpl() throws Exception {
|
public void testTraitFunctionOverriddenByPropertyNoImpl() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyNoImpl.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitFunctionOverriddenByPropertyNoImpl.kt");
|
||||||
@@ -4346,12 +4340,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("traitPropertyOverriddenByFunctionNoImpl.kt")
|
||||||
public void testTraitPropertyOverriddenByFunctionNoImpl() throws Exception {
|
public void testTraitPropertyOverriddenByFunctionNoImpl() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionNoImpl.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/accidentalOverrides/traitPropertyOverriddenByFunctionNoImpl.kt");
|
||||||
@@ -4712,6 +4700,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("twoTraits.kt")
|
||||||
public void testTwoTraits() throws Exception {
|
public void testTwoTraits() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/twoTraits.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/traitImpl/twoTraits.kt");
|
||||||
|
|||||||
@@ -215,12 +215,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@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")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/lazyCodegen")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+15
@@ -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")
|
@TestMetadata("compiler/testData/codegen/boxAgainstJava/notNullAssertions")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+36
@@ -7045,6 +7045,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("kt5495.kt")
|
||||||
public void testKt5495() throws Exception {
|
public void testKt5495() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5495.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/kt5495.kt");
|
||||||
@@ -7057,6 +7075,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("traitWithPrivateExtension.kt")
|
||||||
public void testTraitWithPrivateExtension() throws Exception {
|
public void testTraitWithPrivateExtension() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitWithPrivateExtension.kt");
|
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 org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
||||||
boolean hasBody();
|
boolean hasBody();
|
||||||
|
|
||||||
@@ -27,6 +29,10 @@ public interface PropertyAccessorDescriptor extends FunctionDescriptor {
|
|||||||
@Override
|
@Override
|
||||||
PropertyAccessorDescriptor getOriginal();
|
PropertyAccessorDescriptor getOriginal();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
PropertyDescriptor getCorrespondingProperty();
|
PropertyDescriptor getCorrespondingProperty();
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface PropertyGetterDescriptor extends PropertyAccessorDescriptor {
|
public interface PropertyGetterDescriptor extends PropertyAccessorDescriptor {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
PropertyGetterDescriptor getOriginal();
|
PropertyGetterDescriptor getOriginal();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,14 @@ package org.jetbrains.kotlin.descriptors;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface PropertySetterDescriptor extends PropertyAccessorDescriptor {
|
public interface PropertySetterDescriptor extends PropertyAccessorDescriptor {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
PropertySetterDescriptor getOriginal();
|
PropertySetterDescriptor getOriginal();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
Set<? extends PropertySetterDescriptor> getOverriddenDescriptors();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -56,8 +56,9 @@ public class PropertyGetterDescriptorImpl extends PropertyAccessorDescriptorImpl
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
|
@SuppressWarnings("unchecked")
|
||||||
return super.getOverriddenDescriptors(true);
|
public Set<? extends PropertyGetterDescriptor> getOverriddenDescriptors() {
|
||||||
|
return (Set) super.getOverriddenDescriptors(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+3
-2
@@ -72,8 +72,9 @@ public class PropertySetterDescriptorImpl extends PropertyAccessorDescriptorImpl
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends PropertyAccessorDescriptor> getOverriddenDescriptors() {
|
@SuppressWarnings("unchecked")
|
||||||
return super.getOverriddenDescriptors(false);
|
public Set<? extends PropertySetterDescriptor> getOverriddenDescriptors() {
|
||||||
|
return (Set) super.getOverriddenDescriptors(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user