diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 4db7b07b923..2f09b54f99a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -106,14 +106,15 @@ public abstract class AnnotationCodegen { @Nullable Type returnType, @Nullable KotlinType typeForTypeAnnotations ) { - genAnnotations(annotated, returnType, typeForTypeAnnotations, null); + genAnnotations(annotated, returnType, typeForTypeAnnotations, null, Collections.emptyList()); } public void genAnnotations( @Nullable Annotated annotated, @Nullable Type returnType, @Nullable KotlinType typeForTypeAnnotations, - @Nullable DeclarationDescriptorWithVisibility parameterContainer + @Nullable DeclarationDescriptorWithVisibility parameterContainer, + @NotNull List> additionalAnnotations ) { 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); generateTypeAnnotations(annotated, typeForTypeAnnotations); } @@ -326,11 +332,13 @@ public abstract class AnnotationCodegen { visitor.visitEnd(); } - private void generateAnnotationIfNotPresent(Set annotationDescriptorsAlreadyPresent, Class annotationClass) { + @NotNull + private String generateAnnotationIfNotPresent(Set annotationDescriptorsAlreadyPresent, Class annotationClass) { String descriptor = Type.getType(annotationClass).getDescriptor(); if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { visitAnnotation(descriptor, false).visitEnd(); } + return descriptor; } private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 7e0387c29ad..a8a9927c1a0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -193,6 +193,10 @@ public class FunctionCodegen { if (origin.getOriginKind() == JvmDeclarationOriginKind.SAM_DELEGATION) { flags |= ACC_SYNTHETIC; } + boolean isCompatibilityStubInDefaultImpls = isCompatibilityStubInDefaultImpls(functionDescriptor, methodContext, state.getJvmDefaultMode()); + if (isCompatibilityStubInDefaultImpls) { + flags |= ACC_DEPRECATED; + } if (functionDescriptor.isExternal() && owner instanceof MultifileClassFacadeContext) { // Native methods are only defined in facades and do not need package part implementations @@ -214,7 +218,9 @@ public class FunctionCodegen { 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); @@ -276,7 +282,8 @@ public class FunctionCodegen { @NotNull FunctionDescriptor functionDescriptor, @NotNull Method asmMethod, @NotNull JvmMethodGenericSignature jvmSignature, - @NotNull MethodVisitor mv + @NotNull MethodVisitor mv, + @NotNull List> additionalNoArgAnnotations ) { FunctionDescriptor annotationsOwner; if (shouldHideConstructorDueToInlineClassTypeValueParameters(functionDescriptor)) { @@ -292,7 +299,7 @@ public class FunctionCodegen { } 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); } @@ -536,7 +543,7 @@ public class FunctionCodegen { //noinspection ConstantConditions int parameterIndex = i - syntheticParameterCount; 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 ) { return OwnerKind.DEFAULT_IMPLS == context.getContextKind() && + jvmDefaultMode.isCompatibility() && JvmAnnotationUtilKt.isCompiledToJvmDefault(DescriptorUtils.unwrapFakeOverrideToAnyDeclaration(functionDescriptor), - jvmDefaultMode) && - jvmDefaultMode.isCompatibility(); + jvmDefaultMode); } private static void generateLocalVariableTable( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt index 264a02887d0..aabc42767f1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecation/DeprecationResolver.kt @@ -272,6 +272,6 @@ class DeprecationResolver( } companion object { - private val JAVA_DEPRECATED = FqName("java.lang.Deprecated") + val JAVA_DEPRECATED = FqName("java.lang.Deprecated") } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index 60641960f9a..604531ac1e4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -12,7 +12,9 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPLS") 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_FOR_COMPATIBILITY_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC", isSynthetic = true) object MULTIFILE_BRIDGE : IrDeclarationOriginImpl("MULTIFILE_BRIDGE") object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 75ae7577523..928cd39a775 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -68,7 +68,8 @@ class JvmBackendContext( val typeMapper = IrTypeMapper(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() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index aba10c779f4..1dcb90d588d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -132,7 +132,9 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR && origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR && origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE && + origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY && origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC && + origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC && origin != IrDeclarationOrigin.BRIDGE && origin != IrDeclarationOrigin.BRIDGE_SPECIAL && origin != IrDeclarationOrigin.DELEGATED_MEMBER && diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/JvmSignatureClashDetector.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/JvmSignatureClashDetector.kt index f788b465aeb..fc9e65ce61e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/JvmSignatureClashDetector.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/JvmSignatureClashDetector.kt @@ -179,7 +179,9 @@ class JvmSignatureClashDetector( IrDeclarationOrigin.IR_BUILTINS_STUB, JvmLoweredDeclarationOrigin.TO_ARRAY, 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( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index ca66f2b11fc..0ae1680ad75 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.lower.allOverridden 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.FQ_NAMES 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.name.FqName 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.jvm.jvmSignature.JvmClassSignature import org.jetbrains.kotlin.resolve.source.PsiSourceElement @@ -394,7 +396,11 @@ fun IrClass.isOptionalAnnotationClass(): Boolean = val IrAnnotationContainer.deprecationFlags: Int 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 ?.name?.asString() == DeprecationLevel.HIDDEN.name return Opcodes.ACC_DEPRECATED or if (isHidden) Opcodes.ACC_SYNTHETIC else 0 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt index 59b081fb04e..e64b6e7c764 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDeclarationFactory.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.backend.jvm.descriptors import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper 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.codegen.MethodSignatureMapper 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.ir.UNDEFINED_OFFSET 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.declarations.* 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.JvmAbi import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import java.util.* class JvmDeclarationFactory( + private val context: JvmBackendContext, private val methodSignatureMapper: MethodSignatureMapper, private val languageVersionSettings: LanguageVersionSettings ) : DeclarationFactory { @@ -216,9 +221,10 @@ class JvmDeclarationFactory( } } - fun getDefaultImplsFunction(interfaceFun: IrSimpleFunction): IrSimpleFunction { + fun getDefaultImplsFunction(interfaceFun: IrSimpleFunction, forCompatibilityMode: Boolean = false): IrSimpleFunction { val parent = interfaceFun.parentAsClass 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) { 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`. // The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge. origin = when { - !interfaceFun.isFakeOverride -> interfaceFun.origin - interfaceFun.resolveFakeOverride()!!.origin.isSynthetic -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC - else -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE + !forCompatibilityMode && !interfaceFun.isFakeOverride -> interfaceFun.origin + interfaceFun.resolveFakeOverride()!!.origin.isSynthetic -> + 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. modality = Modality.OPEN, @@ -249,7 +259,15 @@ class JvmDeclarationFactory( isFakeOverride = false, 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) + } + } + } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt index 4e15f8f7e21..ece2c9eaa9f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt @@ -229,7 +229,9 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE */ private fun isDefaultImplsBridge(f: IrSimpleFunction) = 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? { if (!isFakeOverride) return null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index bc1196eee19..0569b1a3507 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny 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.JvmLoweredDeclarationOrigin 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.Modality import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall 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.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver /** * 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) -> { - val defaultImpl = createDefaultImpl(function) - defaultImpl.bridgeViaAccessorTo(function) + createJvmDefaultCompatibilityDelegate(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, ... */ isCompatibilityMode -> { - val defaultImpl = createDefaultImpl(function) - defaultImpl.bridgeViaAccessorTo(function) + createJvmDefaultCompatibilityDelegate(function) } // 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) { // We produce $DefaultImpls for annotation classes only to move $annotations methods (for property annotations) there. val annotationsMethods = @@ -189,8 +195,8 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran } } - private fun createDefaultImpl(function: IrSimpleFunction): IrSimpleFunction = - context.declarationFactory.getDefaultImplsFunction(function).also { newFunction -> + private fun createDefaultImpl(function: IrSimpleFunction, forCompatibility: Boolean = false): IrSimpleFunction = + context.declarationFactory.getDefaultImplsFunction(function, forCompatibility).also { newFunction -> newFunction.parentAsClass.declarations.add(newFunction) } diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.kt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.kt new file mode 100644 index 00000000000..006c77bfea7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.kt @@ -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" + +} diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.txt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.txt new file mode 100644 index 00000000000..b1f6229a927 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecation.txt @@ -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 +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.kt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.kt new file mode 100644 index 00000000000..56938143693 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.kt @@ -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") { + + } +} diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.txt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.txt new file mode 100644 index 00000000000..3b89f672ee1 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/deprecationWithDefault.txt @@ -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 +} diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt index 05700d347bf..392c0ff3407 100644 --- a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt @@ -5,6 +5,8 @@ @JvmDefaultWithoutCompatibility interface NoDefaultImpl { fun test() {} + val prop: String + get() = "123" } interface WithDefaultImpl: NoDefaultImpl { @@ -13,6 +15,8 @@ interface WithDefaultImpl: NoDefaultImpl { interface WithDefaultImplPure { fun test() {} + val prop: String + get() = "123" } @JvmDefaultWithoutCompatibility diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.txt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.txt index 8073d5cf0ad..489ce7753a0 100644 --- a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.txt +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.txt @@ -7,6 +7,7 @@ public final class KotlinClass { @kotlin.jvm.JvmDefaultWithoutCompatibility @kotlin.Metadata public interface NoDefaultImpl { + public @org.jetbrains.annotations.NotNull method getProp(): java.lang.String public method test(): void } @@ -19,24 +20,29 @@ public interface NoDefaultImpl2FromDefaultImpls { @kotlin.Metadata public final 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 public interface WithDefaultImpl { 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 } @kotlin.Metadata public final 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 public interface WithDefaultImplPure { 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 @org.jetbrains.annotations.NotNull method getProp(): java.lang.String public method test(): void } diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndAny.txt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndAny.txt index ddefe138132..6ab5966aa58 100644 --- a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndAny.txt +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndAny.txt @@ -11,7 +11,7 @@ public class B { @kotlin.Metadata public final 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 @@ -24,7 +24,7 @@ public interface Base { @kotlin.Metadata public final 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 @@ -37,7 +37,7 @@ public interface Derived { @kotlin.Metadata public final 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 diff --git a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndNullable.txt b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndNullable.txt index ddefe138132..6ab5966aa58 100644 --- a/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndNullable.txt +++ b/compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/specialization/primitiveAndNullable.txt @@ -11,7 +11,7 @@ public class B { @kotlin.Metadata public final 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 @@ -24,7 +24,7 @@ public interface Base { @kotlin.Metadata public final 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 @@ -37,7 +37,7 @@ public interface Derived { @kotlin.Metadata public final 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 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 822d5f609ed..1ae91508dd5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -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); } + @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") public void testJvmDefaultWithoutCompatibility() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index e6ee18688d1..ecb9ecbd650 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -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); } + @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") public void testJvmDefaultWithoutCompatibility() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/jvm8/defaults/allCompatibility/jvmDefaultWithoutCompatibility.kt");