Deprecate DefaultImpl methods in compatibility mode

This commit is contained in:
Mikhail Bogdanov
2020-06-19 13:05:32 +02:00
parent 39740ce440
commit 41511898a1
21 changed files with 234 additions and 33 deletions
@@ -106,14 +106,15 @@ public abstract class AnnotationCodegen {
@Nullable Type returnType, @Nullable Type returnType,
@Nullable KotlinType typeForTypeAnnotations @Nullable KotlinType typeForTypeAnnotations
) { ) {
genAnnotations(annotated, returnType, typeForTypeAnnotations, null); genAnnotations(annotated, returnType, typeForTypeAnnotations, null, Collections.emptyList());
} }
public void genAnnotations( public void genAnnotations(
@Nullable Annotated annotated, @Nullable Annotated annotated,
@Nullable Type returnType, @Nullable Type returnType,
@Nullable KotlinType typeForTypeAnnotations, @Nullable KotlinType typeForTypeAnnotations,
@Nullable DeclarationDescriptorWithVisibility parameterContainer @Nullable DeclarationDescriptorWithVisibility parameterContainer,
@NotNull List<Class<?>> additionalAnnotations
) { ) {
if (annotated == null) return; if (annotated == null) return;
@@ -148,6 +149,11 @@ public abstract class AnnotationCodegen {
} }
} }
for (Class<?> annotation : additionalAnnotations) {
String descriptor = generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotation);
annotationDescriptorsAlreadyPresent.add(descriptor);
}
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer); generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer);
generateTypeAnnotations(annotated, typeForTypeAnnotations); generateTypeAnnotations(annotated, typeForTypeAnnotations);
} }
@@ -326,11 +332,13 @@ public abstract class AnnotationCodegen {
visitor.visitEnd(); visitor.visitEnd();
} }
private void generateAnnotationIfNotPresent(Set<String> annotationDescriptorsAlreadyPresent, Class<?> annotationClass) { @NotNull
private String generateAnnotationIfNotPresent(Set<String> annotationDescriptorsAlreadyPresent, Class<?> annotationClass) {
String descriptor = Type.getType(annotationClass).getDescriptor(); String descriptor = Type.getType(annotationClass).getDescriptor();
if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) {
visitAnnotation(descriptor, false).visitEnd(); visitAnnotation(descriptor, false).visitEnd();
} }
return descriptor;
} }
private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) { private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) {
@@ -193,6 +193,10 @@ public class FunctionCodegen {
if (origin.getOriginKind() == JvmDeclarationOriginKind.SAM_DELEGATION) { if (origin.getOriginKind() == JvmDeclarationOriginKind.SAM_DELEGATION) {
flags |= ACC_SYNTHETIC; flags |= ACC_SYNTHETIC;
} }
boolean isCompatibilityStubInDefaultImpls = isCompatibilityStubInDefaultImpls(functionDescriptor, methodContext, state.getJvmDefaultMode());
if (isCompatibilityStubInDefaultImpls) {
flags |= ACC_DEPRECATED;
}
if (functionDescriptor.isExternal() && owner instanceof MultifileClassFacadeContext) { if (functionDescriptor.isExternal() && owner instanceof MultifileClassFacadeContext) {
// Native methods are only defined in facades and do not need package part implementations // Native methods are only defined in facades and do not need package part implementations
@@ -214,7 +218,9 @@ public class FunctionCodegen {
recordMethodForFunctionIfAppropriate(functionDescriptor, asmMethod); recordMethodForFunctionIfAppropriate(functionDescriptor, asmMethod);
generateMethodAnnotationsIfRequired(functionDescriptor, asmMethod, jvmSignature, mv); generateMethodAnnotationsIfRequired(functionDescriptor, asmMethod, jvmSignature, mv, isCompatibilityStubInDefaultImpls
? Collections.singletonList(Deprecated.class)
: Collections.emptyList());
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0); GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0);
@@ -276,7 +282,8 @@ public class FunctionCodegen {
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
@NotNull Method asmMethod, @NotNull Method asmMethod,
@NotNull JvmMethodGenericSignature jvmSignature, @NotNull JvmMethodGenericSignature jvmSignature,
@NotNull MethodVisitor mv @NotNull MethodVisitor mv,
@NotNull List<Class<?>> additionalNoArgAnnotations
) { ) {
FunctionDescriptor annotationsOwner; FunctionDescriptor annotationsOwner;
if (shouldHideConstructorDueToInlineClassTypeValueParameters(functionDescriptor)) { if (shouldHideConstructorDueToInlineClassTypeValueParameters(functionDescriptor)) {
@@ -292,7 +299,7 @@ public class FunctionCodegen {
} }
AnnotationCodegen.forMethod(mv, memberCodegen, state) AnnotationCodegen.forMethod(mv, memberCodegen, state)
.genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType()); .genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType(), null, additionalNoArgAnnotations);
generateParameterAnnotations(annotationsOwner, mv, jvmSignature, memberCodegen, state); generateParameterAnnotations(annotationsOwner, mv, jvmSignature, memberCodegen, state);
} }
@@ -536,7 +543,7 @@ public class FunctionCodegen {
//noinspection ConstantConditions //noinspection ConstantConditions
int parameterIndex = i - syntheticParameterCount; int parameterIndex = i - syntheticParameterCount;
AnnotationCodegen.forParameter(parameterIndex, mv, memberCodegen, state) AnnotationCodegen.forParameter(parameterIndex, mv, memberCodegen, state)
.genAnnotations(annotated, parameterSignature.getAsmType(), annotated.getReturnType(), functionDescriptor); .genAnnotations(annotated, parameterSignature.getAsmType(), annotated.getReturnType(), functionDescriptor, Collections.emptyList());
} }
} }
} }
@@ -712,9 +719,9 @@ public class FunctionCodegen {
@NotNull JvmDefaultMode jvmDefaultMode @NotNull JvmDefaultMode jvmDefaultMode
) { ) {
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() && return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
jvmDefaultMode.isCompatibility() &&
JvmAnnotationUtilKt.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor), JvmAnnotationUtilKt.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor),
jvmDefaultMode) && jvmDefaultMode);
jvmDefaultMode.isCompatibility();
} }
private static void generateLocalVariableTable( private static void generateLocalVariableTable(
@@ -272,6 +272,6 @@ class DeprecationResolver(
} }
companion object { companion object {
private val JAVA_DEPRECATED = FqName("java.lang.Deprecated") val JAVA_DEPRECATED = FqName("java.lang.Deprecated")
} }
} }
@@ -12,7 +12,9 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPLS") object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPLS")
object DEFAULT_IMPLS_BRIDGE : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE") object DEFAULT_IMPLS_BRIDGE : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE")
object DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY")
object DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC", isSynthetic = true) object DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC", isSynthetic = true)
object DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC", isSynthetic = true)
object MULTIFILE_BRIDGE : IrDeclarationOriginImpl("MULTIFILE_BRIDGE") object MULTIFILE_BRIDGE : IrDeclarationOriginImpl("MULTIFILE_BRIDGE")
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL") object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL")
@@ -68,7 +68,8 @@ class JvmBackendContext(
val typeMapper = IrTypeMapper(this) val typeMapper = IrTypeMapper(this)
val methodSignatureMapper = MethodSignatureMapper(this) val methodSignatureMapper = MethodSignatureMapper(this)
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper, state.languageVersionSettings) override val declarationFactory: JvmDeclarationFactory =
JvmDeclarationFactory(this, methodSignatureMapper, state.languageVersionSettings)
override val mapping: Mapping = DefaultMapping() override val mapping: Mapping = DefaultMapping()
@@ -132,7 +132,9 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR && origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR && origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE && origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC && origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC &&
origin != IrDeclarationOrigin.BRIDGE && origin != IrDeclarationOrigin.BRIDGE &&
origin != IrDeclarationOrigin.BRIDGE_SPECIAL && origin != IrDeclarationOrigin.BRIDGE_SPECIAL &&
origin != IrDeclarationOrigin.DELEGATED_MEMBER && origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
@@ -179,7 +179,9 @@ class JvmSignatureClashDetector(
IrDeclarationOrigin.IR_BUILTINS_STUB, IrDeclarationOrigin.IR_BUILTINS_STUB,
JvmLoweredDeclarationOrigin.TO_ARRAY, JvmLoweredDeclarationOrigin.TO_ARRAY,
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE,
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY,
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC,
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
) )
val PREDEFINED_SIGNATURES = listOf( val PREDEFINED_SIGNATURES = listOf(
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.lower.allOverridden import org.jetbrains.kotlin.backend.common.lower.allOverridden
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.inline.* import org.jetbrains.kotlin.resolve.inline.*
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement
@@ -394,7 +396,11 @@ fun IrClass.isOptionalAnnotationClass(): Boolean =
val IrAnnotationContainer.deprecationFlags: Int val IrAnnotationContainer.deprecationFlags: Int
get() { get() {
val annotation = annotations.findAnnotation(FQ_NAMES.deprecated) ?: return 0 val annotation = annotations.findAnnotation(FQ_NAMES.deprecated)
?: return if ((this as? IrDeclaration)?.origin?.let {
it == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
} == true
) Opcodes.ACC_DEPRECATED else 0
val isHidden = (annotation.getValueArgument(2) as? IrGetEnumValue)?.symbol?.owner val isHidden = (annotation.getValueArgument(2) as? IrGetEnumValue)?.symbol?.owner
?.name?.asString() == DeprecationLevel.HIDDEN.name ?.name?.asString() == DeprecationLevel.HIDDEN.name
return Opcodes.ACC_DEPRECATED or if (isHidden) Opcodes.ACC_SYNTHETIC else 0 return Opcodes.ACC_DEPRECATED or if (isHidden) Opcodes.ACC_SYNTHETIC else 0
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper
import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
@@ -21,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.setSourceRange import org.jetbrains.kotlin.ir.builders.setSourceRange
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
@@ -39,9 +42,11 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import java.util.* import java.util.*
class JvmDeclarationFactory( class JvmDeclarationFactory(
private val context: JvmBackendContext,
private val methodSignatureMapper: MethodSignatureMapper, private val methodSignatureMapper: MethodSignatureMapper,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings
) : DeclarationFactory { ) : DeclarationFactory {
@@ -216,9 +221,10 @@ class JvmDeclarationFactory(
} }
} }
fun getDefaultImplsFunction(interfaceFun: IrSimpleFunction): IrSimpleFunction { fun getDefaultImplsFunction(interfaceFun: IrSimpleFunction, forCompatibilityMode: Boolean = false): IrSimpleFunction {
val parent = interfaceFun.parentAsClass val parent = interfaceFun.parentAsClass
assert(parent.isJvmInterface) { "Parent of ${interfaceFun.dump()} should be interface" } assert(parent.isJvmInterface) { "Parent of ${interfaceFun.dump()} should be interface" }
assert(!forCompatibilityMode || !defaultImplsMethods.containsKey(interfaceFun)) { "DefaultImpls stub in compatibility mode should be requested only once from interface lowering: ${interfaceFun.dump()}" }
return defaultImplsMethods.getOrPut(interfaceFun) { return defaultImplsMethods.getOrPut(interfaceFun) {
val defaultImpls = getDefaultImplsClass(interfaceFun.parentAsClass) val defaultImpls = getDefaultImplsClass(interfaceFun.parentAsClass)
@@ -235,9 +241,13 @@ class JvmDeclarationFactory(
// is supposed to allow using `I2.DefaultImpls.f` as if it was inherited from `I1.DefaultImpls`. // is supposed to allow using `I2.DefaultImpls.f` as if it was inherited from `I1.DefaultImpls`.
// The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge. // The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge.
origin = when { origin = when {
!interfaceFun.isFakeOverride -> interfaceFun.origin !forCompatibilityMode && !interfaceFun.isFakeOverride -> interfaceFun.origin
interfaceFun.resolveFakeOverride()!!.origin.isSynthetic -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC interfaceFun.resolveFakeOverride()!!.origin.isSynthetic ->
else -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE if (forCompatibilityMode) JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
else JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
else ->
if (forCompatibilityMode) JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
else JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE
}, },
// Old backend doesn't generate ACC_FINAL on DefaultImpls methods. // Old backend doesn't generate ACC_FINAL on DefaultImpls methods.
modality = Modality.OPEN, modality = Modality.OPEN,
@@ -249,7 +259,15 @@ class JvmDeclarationFactory(
isFakeOverride = false, isFakeOverride = false,
typeParametersFromContext = parent.typeParameters typeParametersFromContext = parent.typeParameters
) ).also {
if (it.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY &&
!it.annotations.hasAnnotation(DeprecationResolver.JAVA_DEPRECATED)
) {
this@JvmDeclarationFactory.context.createIrBuilder(it.symbol).run {
it.annotations += irCall(this@JvmDeclarationFactory.context.ir.symbols.javaLangDeprecatedConstructor)
}
}
}
} }
} }
@@ -229,7 +229,9 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE
*/ */
private fun isDefaultImplsBridge(f: IrSimpleFunction) = private fun isDefaultImplsBridge(f: IrSimpleFunction) =
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE || f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY ||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC ||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDefaultMode): IrSimpleFunction? { internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDefaultMode): IrSimpleFunction? {
if (!isFakeOverride) return null if (!isFakeOverride) return null
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
@@ -27,6 +29,7 @@ import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
/** /**
* This phase moves interface members with default implementations to the * This phase moves interface members with default implementations to the
@@ -114,8 +117,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
} }
} }
isCompatibilityMode && implementation.isCompiledToJvmDefault(jvmDefaultMode) -> { isCompatibilityMode && implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
val defaultImpl = createDefaultImpl(function) createJvmDefaultCompatibilityDelegate(function)
defaultImpl.bridgeViaAccessorTo(function)
} }
} }
} }
@@ -147,8 +149,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
* 5) JVM default declaration is bridged in DefaultImpls via accessor if in compatibility mode, ... * 5) JVM default declaration is bridged in DefaultImpls via accessor if in compatibility mode, ...
*/ */
isCompatibilityMode -> { isCompatibilityMode -> {
val defaultImpl = createDefaultImpl(function) createJvmDefaultCompatibilityDelegate(function)
defaultImpl.bridgeViaAccessorTo(function)
} }
// 6) ... otherwise we simply leave the default function implementation on the interface. // 6) ... otherwise we simply leave the default function implementation on the interface.
@@ -176,6 +177,11 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
} }
} }
private fun createJvmDefaultCompatibilityDelegate(function: IrSimpleFunction) {
val defaultImpl = createDefaultImpl(function, true)
defaultImpl.bridgeViaAccessorTo(function)
}
private fun handleAnnotationClass(irClass: IrClass) { private fun handleAnnotationClass(irClass: IrClass) {
// We produce $DefaultImpls for annotation classes only to move $annotations methods (for property annotations) there. // We produce $DefaultImpls for annotation classes only to move $annotations methods (for property annotations) there.
val annotationsMethods = val annotationsMethods =
@@ -189,8 +195,8 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
} }
} }
private fun createDefaultImpl(function: IrSimpleFunction): IrSimpleFunction = private fun createDefaultImpl(function: IrSimpleFunction, forCompatibility: Boolean = false): IrSimpleFunction =
context.declarationFactory.getDefaultImplsFunction(function).also { newFunction -> context.declarationFactory.getDefaultImplsFunction(function, forCompatibility).also { newFunction ->
newFunction.parentAsClass.declarations.add(newFunction) newFunction.parentAsClass.declarations.add(newFunction)
} }
@@ -0,0 +1,27 @@
// !JVM_DEFAULT_MODE: all-compatibility
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Base {
fun test() {}
val prop: String
get() = "123"
fun withDefault(s: String = "123") {
}
}
interface Derived: Base {
}
interface Deprecated {
@java.lang.Deprecated
fun test() {
}
val prop: String
@java.lang.Deprecated get() = "123"
}
@@ -0,0 +1,52 @@
@kotlin.Metadata
public final class Base$DefaultImpls {
inner class Base$DefaultImpls
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: Base): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: Base): void
public synthetic static method withDefault$default(p0: Base, p1: java.lang.String, p2: int, p3: java.lang.Object): void
public deprecated static @java.lang.Deprecated method withDefault(@org.jetbrains.annotations.NotNull p0: Base, @org.jetbrains.annotations.NotNull p1: java.lang.String): void
}
@kotlin.Metadata
public interface Base {
inner class Base$DefaultImpls
public synthetic static method access$getProp$jd(p0: Base): java.lang.String
public synthetic static method access$test$jd(p0: Base): void
public synthetic static method access$withDefault$jd(p0: Base, p1: java.lang.String): void
public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
public method test(): void
public synthetic static method withDefault$default(p0: Base, p1: java.lang.String, p2: int, p3: java.lang.Object): void
public method withDefault(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
}
@kotlin.Metadata
public final class Deprecated$DefaultImpls {
inner class Deprecated$DefaultImpls
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: Deprecated): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: Deprecated): void
}
@kotlin.Metadata
public interface Deprecated {
inner class Deprecated$DefaultImpls
public synthetic static method access$getProp$jd(p0: Deprecated): java.lang.String
public synthetic static method access$test$jd(p0: Deprecated): void
public @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
public @java.lang.Deprecated method test(): void
}
@kotlin.Metadata
public final class Derived$DefaultImpls {
inner class Derived$DefaultImpls
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: Derived): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: Derived): void
public deprecated static @java.lang.Deprecated method withDefault(@org.jetbrains.annotations.NotNull p0: Derived, @org.jetbrains.annotations.NotNull p1: java.lang.String): void
}
@kotlin.Metadata
public interface Derived {
inner class Derived$DefaultImpls
public synthetic static method access$getProp$jd(p0: Derived): java.lang.String
public synthetic static method access$test$jd(p0: Derived): void
public synthetic static method access$withDefault$jd(p0: Derived, p1: java.lang.String): void
}
@@ -0,0 +1,18 @@
// !JVM_DEFAULT_MODE: all-compatibility
// JVM_TARGET: 1.8
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
// IR copies annotations to default impls
interface Deprecated {
@java.lang.Deprecated
fun test() {
}
val prop: String
@java.lang.Deprecated get() = "123"
@java.lang.Deprecated
fun withDefault(s: String = "123") {
}
}
@@ -0,0 +1,20 @@
@kotlin.Metadata
public final class Deprecated$DefaultImpls {
inner class Deprecated$DefaultImpls
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: Deprecated): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: Deprecated): void
public synthetic static method withDefault$default(p0: Deprecated, p1: java.lang.String, p2: int, p3: java.lang.Object): void
public deprecated static @java.lang.Deprecated method withDefault(@org.jetbrains.annotations.NotNull p0: Deprecated, @org.jetbrains.annotations.NotNull p1: java.lang.String): void
}
@kotlin.Metadata
public interface Deprecated {
inner class Deprecated$DefaultImpls
public synthetic static method access$getProp$jd(p0: Deprecated): java.lang.String
public synthetic static method access$test$jd(p0: Deprecated): void
public synthetic static method access$withDefault$jd(p0: Deprecated, p1: java.lang.String): void
public @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
public @java.lang.Deprecated method test(): void
public synthetic static method withDefault$default(p0: Deprecated, p1: java.lang.String, p2: int, p3: java.lang.Object): void
public @java.lang.Deprecated method withDefault(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
}
@@ -5,6 +5,8 @@
@JvmDefaultWithoutCompatibility @JvmDefaultWithoutCompatibility
interface NoDefaultImpl { interface NoDefaultImpl {
fun test() {} fun test() {}
val prop: String
get() = "123"
} }
interface WithDefaultImpl: NoDefaultImpl { interface WithDefaultImpl: NoDefaultImpl {
@@ -13,6 +15,8 @@ interface WithDefaultImpl: NoDefaultImpl {
interface WithDefaultImplPure { interface WithDefaultImplPure {
fun test() {} fun test() {}
val prop: String
get() = "123"
} }
@JvmDefaultWithoutCompatibility @JvmDefaultWithoutCompatibility
@@ -7,6 +7,7 @@ public final class KotlinClass {
@kotlin.jvm.JvmDefaultWithoutCompatibility @kotlin.jvm.JvmDefaultWithoutCompatibility
@kotlin.Metadata @kotlin.Metadata
public interface NoDefaultImpl { public interface NoDefaultImpl {
public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
public method test(): void public method test(): void
} }
@@ -19,24 +20,29 @@ public interface NoDefaultImpl2FromDefaultImpls {
@kotlin.Metadata @kotlin.Metadata
public final class WithDefaultImpl$DefaultImpls { public final class WithDefaultImpl$DefaultImpls {
inner class WithDefaultImpl$DefaultImpls inner class WithDefaultImpl$DefaultImpls
public static method test(@org.jetbrains.annotations.NotNull p0: WithDefaultImpl): void public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: WithDefaultImpl): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: WithDefaultImpl): void
} }
@kotlin.Metadata @kotlin.Metadata
public interface WithDefaultImpl { public interface WithDefaultImpl {
inner class WithDefaultImpl$DefaultImpls inner class WithDefaultImpl$DefaultImpls
public synthetic static method access$getProp$jd(p0: WithDefaultImpl): java.lang.String
public synthetic static method access$test$jd(p0: WithDefaultImpl): void public synthetic static method access$test$jd(p0: WithDefaultImpl): void
} }
@kotlin.Metadata @kotlin.Metadata
public final class WithDefaultImplPure$DefaultImpls { public final class WithDefaultImplPure$DefaultImpls {
inner class WithDefaultImplPure$DefaultImpls inner class WithDefaultImplPure$DefaultImpls
public static method test(@org.jetbrains.annotations.NotNull p0: WithDefaultImplPure): void public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method getProp(@org.jetbrains.annotations.NotNull p0: WithDefaultImplPure): java.lang.String
public deprecated static @java.lang.Deprecated method test(@org.jetbrains.annotations.NotNull p0: WithDefaultImplPure): void
} }
@kotlin.Metadata @kotlin.Metadata
public interface WithDefaultImplPure { public interface WithDefaultImplPure {
inner class WithDefaultImplPure$DefaultImpls inner class WithDefaultImplPure$DefaultImpls
public synthetic static method access$getProp$jd(p0: WithDefaultImplPure): java.lang.String
public synthetic static method access$test$jd(p0: WithDefaultImplPure): void public synthetic static method access$test$jd(p0: WithDefaultImplPure): void
public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String
public method test(): void public method test(): void
} }
@@ -11,7 +11,7 @@ public class B {
@kotlin.Metadata @kotlin.Metadata
public final class Base$DefaultImpls { public final class Base$DefaultImpls {
inner class Base$DefaultImpls inner class Base$DefaultImpls
public static @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: Base): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: Base): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -24,7 +24,7 @@ public interface Base {
@kotlin.Metadata @kotlin.Metadata
public final class Derived$DefaultImpls { public final class Derived$DefaultImpls {
inner class Derived$DefaultImpls inner class Derived$DefaultImpls
public static @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Derived): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Derived): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -37,7 +37,7 @@ public interface Derived {
@kotlin.Metadata @kotlin.Metadata
public final class Mixed$DefaultImpls { public final class Mixed$DefaultImpls {
inner class Mixed$DefaultImpls inner class Mixed$DefaultImpls
public static @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Mixed): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Mixed): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -11,7 +11,7 @@ public class B {
@kotlin.Metadata @kotlin.Metadata
public final class Base$DefaultImpls { public final class Base$DefaultImpls {
inner class Base$DefaultImpls inner class Base$DefaultImpls
public static @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: Base): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: Base): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -24,7 +24,7 @@ public interface Base {
@kotlin.Metadata @kotlin.Metadata
public final class Derived$DefaultImpls { public final class Derived$DefaultImpls {
inner class Derived$DefaultImpls inner class Derived$DefaultImpls
public static @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Derived): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Derived): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -37,7 +37,7 @@ public interface Derived {
@kotlin.Metadata @kotlin.Metadata
public final class Mixed$DefaultImpls { public final class Mixed$DefaultImpls {
inner class Mixed$DefaultImpls inner class Mixed$DefaultImpls
public static @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Mixed): java.lang.Integer public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Mixed): java.lang.Integer
} }
@kotlin.Metadata @kotlin.Metadata
@@ -517,6 +517,16 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility"), Pattern.compile("^(.+)\\.kt$"), null, true); KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility"), Pattern.compile("^(.+)\\.kt$"), null, true);
} }
@TestMetadata("deprecation.kt")
public void testDeprecation() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.kt");
}
@TestMetadata("deprecationWithDefault.kt")
public void testDeprecationWithDefault() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.kt");
}
@TestMetadata("jvmDefaultWithoutCompatibility.kt") @TestMetadata("jvmDefaultWithoutCompatibility.kt")
public void testJvmDefaultWithoutCompatibility() throws Exception { public void testJvmDefaultWithoutCompatibility() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt"); runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt");
@@ -487,6 +487,16 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
} }
@TestMetadata("deprecation.kt")
public void testDeprecation() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.kt");
}
@TestMetadata("deprecationWithDefault.kt")
public void testDeprecationWithDefault() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.kt");
}
@TestMetadata("jvmDefaultWithoutCompatibility.kt") @TestMetadata("jvmDefaultWithoutCompatibility.kt")
public void testJvmDefaultWithoutCompatibility() throws Exception { public void testJvmDefaultWithoutCompatibility() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt"); runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt");