diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 9f566e9e080..f6850fe0bc7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -22,9 +22,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.HashCode; import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; -import org.jetbrains.kotlin.config.JvmTarget; -import org.jetbrains.kotlin.config.LanguageFeature; -import org.jetbrains.kotlin.config.LanguageVersionSettings; +import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; @@ -308,9 +306,9 @@ public class AsmUtil { return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes)); } - public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { + public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind, JvmDefaultMode jvmDefaultMode) { return (functionDescriptor.getModality() == Modality.ABSTRACT || - (isJvmInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor))) + (isJvmInterface(functionDescriptor.getContainingDeclaration()) && !hasJvmDefaultAnnotation(functionDescriptor, jvmDefaultMode))) && !isStaticMethod(kind, functionDescriptor); } @@ -325,10 +323,15 @@ public class AsmUtil { } public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind, GenerationState state) { - return getMethodAsmFlags(functionDescriptor, kind, state.getDeprecationProvider()); + return getMethodAsmFlags(functionDescriptor, kind, state.getDeprecationProvider(), state.getJvmDefaultMode()); } - public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind, DeprecationResolver deprecationResolver) { + public static int getMethodAsmFlags( + FunctionDescriptor functionDescriptor, + OwnerKind kind, + DeprecationResolver deprecationResolver, + JvmDefaultMode jvmDefaultMode + ) { int flags = getCommonCallableFlags(functionDescriptor, kind, deprecationResolver); for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.METHOD_FLAGS) { @@ -356,7 +359,7 @@ public class AsmUtil { flags |= ACC_STATIC; } - if (isAbstractMethod(functionDescriptor, kind)) { + if (isAbstractMethod(functionDescriptor, kind, jvmDefaultMode)) { flags |= ACC_ABSTRACT; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java index ab816d7d1ce..b4c690e7cb2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java @@ -222,7 +222,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) { FunctionDescriptor interfaceFun = entry.getKey(); //skip java 8 default methods - if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !hasJvmDefaultAnnotation(interfaceFun)) { + if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !hasJvmDefaultAnnotation(interfaceFun, state.getJvmDefaultMode())) { generateDelegationToDefaultImpl(interfaceFun, entry.getValue()); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 87eba83702a..474f279588c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -447,7 +447,7 @@ public class FunctionCodegen { ) { OwnerKind contextKind = methodContext.getContextKind(); if (!state.getClassBuilderMode().generateBodies - || isAbstractMethod(functionDescriptor, contextKind) + || isAbstractMethod(functionDescriptor, contextKind, state.getJvmDefaultMode()) || shouldSkipMethodBodyInAbiMode(state.getClassBuilderMode(), origin) ) { generateLocalVariableTable( @@ -732,7 +732,7 @@ public class FunctionCodegen { @NotNull JvmDefaultMode jvmDefaultMode ) { return OwnerKind.DEFAULT_IMPLS == context.getContextKind() && - hasJvmDefaultAnnotation(functionDescriptor) && + hasJvmDefaultAnnotation(functionDescriptor, jvmDefaultMode) && jvmDefaultMode.isCompatibility(); } @@ -1000,7 +1000,7 @@ public class FunctionCodegen { public void generateBridges(@NotNull FunctionDescriptor descriptor) { if (descriptor instanceof ConstructorDescriptor) return; if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return; - if (JvmBridgesImplKt.isAbstractOnJvmIgnoringActualModality(descriptor)) return; + if (JvmBridgesImplKt.isAbstractOnJvmIgnoringActualModality(descriptor, state.getJvmDefaultMode())) return; // equals(Any?), hashCode(), toString() never need bridges if (isMethodOfAny(descriptor)) return; @@ -1036,7 +1036,7 @@ public class FunctionCodegen { } } - if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) { + if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state.getJvmDefaultMode())) { CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor); assert overridden != null; @@ -1460,7 +1460,7 @@ public class FunctionCodegen { iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false); } else { - if (hasJvmDefaultAnnotation(descriptor)) { + if (hasJvmDefaultAnnotation(descriptor, state.getJvmDefaultMode())) { iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor()); } else { @@ -1650,7 +1650,7 @@ public class FunctionCodegen { assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " + containingDeclaration; - if (hasJvmDefaultAnnotation(memberDescriptor)) { + if (hasJvmDefaultAnnotation(memberDescriptor, mode)) { return (kind != OwnerKind.DEFAULT_IMPLS && !isSynthetic) || (kind == OwnerKind.DEFAULT_IMPLS && (isSynthetic || mode.isCompatibility())); } else { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt index 1605835e51e..f742e0e2945 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmBridgesImpl.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.backend.common.bridges.* import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -29,17 +30,17 @@ class DescriptorBasedFunctionHandleForJvm( For non-@JvmDefault interfaces function, its body is generated in a separate place (DefaultImpls) and the method in the interface is abstract so we must not generate bridges for such cases. */ - override val isAbstract: Boolean = super.isAbstract || isAbstractOnJvmIgnoringActualModality(descriptor) + override val isAbstract: Boolean = super.isAbstract || isAbstractOnJvmIgnoringActualModality(descriptor, state.jvmDefaultMode) override val mayBeUsedAsSuperImplementation: Boolean = - super.mayBeUsedAsSuperImplementation || descriptor.isJvmDefaultOrPlatformDependent() + super.mayBeUsedAsSuperImplementation || descriptor.isJvmDefaultOrPlatformDependent(state.jvmDefaultMode) private val asmMethod by lazy(LazyThreadSafetyMode.NONE) { state.typeMapper.mapAsmMethod(descriptor) } override val isDeclaration: Boolean = - descriptor.kind.isReal || needToGenerateDelegationToDefaultImpls(descriptor) + descriptor.kind.isReal || needToGenerateDelegationToDefaultImpls(descriptor, state.jvmDefaultMode) override val mightBeIncorrectCode: Boolean get() = state.classBuilderMode.mightBeIncorrectCode @@ -65,23 +66,23 @@ private fun FunctionDescriptor.containerEntityForEqualityAndHashCode(): Any = private val FunctionDescriptor.isJavaForKotlinOverrideProperty: Boolean get() = this is PropertyAccessorDescriptor && correspondingProperty is JavaForKotlinOverridePropertyDescriptor -private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent() = - hasJvmDefaultAnnotation() || hasPlatformDependentAnnotation() +private fun CallableMemberDescriptor.isJvmDefaultOrPlatformDependent(jvmDefaultMode: JvmDefaultMode) = + hasJvmDefaultAnnotation(jvmDefaultMode) || hasPlatformDependentAnnotation() -private fun needToGenerateDelegationToDefaultImpls(descriptor: FunctionDescriptor): Boolean { +private fun needToGenerateDelegationToDefaultImpls(descriptor: FunctionDescriptor, jvmDefaultMode: JvmDefaultMode): Boolean { if (findInterfaceImplementation(descriptor) == null) return false val overriddenFromInterface = findImplementationFromInterface(descriptor) ?: return false - return !overriddenFromInterface.isJvmDefaultOrPlatformDependent() + return !overriddenFromInterface.isJvmDefaultOrPlatformDependent(jvmDefaultMode) } /** * @return return true for interface method not annotated with @JvmDefault or @PlatformDependent */ -fun isAbstractOnJvmIgnoringActualModality(descriptor: FunctionDescriptor): Boolean { +fun isAbstractOnJvmIgnoringActualModality(descriptor: FunctionDescriptor, jvmDefaultMode: JvmDefaultMode): Boolean { if (!DescriptorUtils.isInterface(descriptor.containingDeclaration)) return false - return !descriptor.isJvmDefaultOrPlatformDependent() + return !descriptor.isJvmDefaultOrPlatformDependent(jvmDefaultMode) } fun generateBridgesForFunctionDescriptorForJvm( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index f56c63ce151..8489dddfdee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.config.ApiVersion; import org.jetbrains.kotlin.config.JvmAnalysisFlags; +import org.jetbrains.kotlin.config.JvmDefaultMode; import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; @@ -67,7 +68,7 @@ public class JvmCodegenUtil { private JvmCodegenUtil() { } - public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor) { + public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor, @NotNull JvmDefaultMode jvmDefaultMode) { if (!isJvmInterface(descriptor.getContainingDeclaration())) { return false; } @@ -75,7 +76,7 @@ public class JvmCodegenUtil { return descriptor.getModality() == Modality.ABSTRACT; } - return !hasJvmDefaultAnnotation(descriptor); + return !hasJvmDefaultAnnotation(descriptor, jvmDefaultMode); } public static boolean isJvmInterface(@Nullable DeclarationDescriptor descriptor) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 2c233fa850e..07f6e2abb07 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -402,7 +402,7 @@ public abstract class MemberCodegen accessor : ((CodegenContext) context).getAccessors()) { - boolean hasJvmDefaultAnnotation = hasJvmDefaultAnnotation(accessor.getCalleeDescriptor()); + boolean hasJvmDefaultAnnotation = hasJvmDefaultAnnotation(accessor.getCalleeDescriptor(), state.getJvmDefaultMode()); OwnerKind kind = context.getContextKind(); if (!isInterface(context.getContextDescriptor()) || @@ -934,7 +934,7 @@ public abstract class MemberCodegen { @NotNull D descriptor, @Nullable ClassDescriptor superCallTarget, @NotNull GenerationState state) { - if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor)) { + if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor, state.getJvmDefaultMode())) { CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext(); CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget); assert c != null : "Couldn't find a context for a super-call: " + descriptor; @@ -593,8 +593,8 @@ public abstract class CodegenContext { CodegenContext properContext = getFirstCrossInlineOrNonInlineContext(); DeclarationDescriptor enclosing = descriptor.getContainingDeclaration(); boolean isInliningContext = properContext.isInlineMethodContext(); - boolean sameJvmDefault = hasJvmDefaultAnnotation(descriptor) == - isCallableMemberWithJvmDefaultAnnotation(properContext.contextDescriptor) || + boolean sameJvmDefault = hasJvmDefaultAnnotation(descriptor, getState().getJvmDefaultMode()) == + isCallableMemberWithJvmDefaultAnnotation(properContext.contextDescriptor, getState().getJvmDefaultMode()) || properContext.contextDescriptor instanceof AccessorForCallableDescriptor; if (!isInliningContext && ( !properContext.hasThisDescriptor() || @@ -651,7 +651,7 @@ public abstract class CodegenContext { return descriptor; } - if (hasJvmDefaultAnnotation(descriptor) && descriptorContext instanceof DefaultImplsClassContext) { + if (hasJvmDefaultAnnotation(descriptor, getState().getJvmDefaultMode()) && descriptorContext instanceof DefaultImplsClassContext) { descriptorContext = ((DefaultImplsClassContext) descriptorContext).getInterfaceContext(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index c9f91a0f351..77b1f5c3acc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -408,7 +408,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid when { DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor && - !innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() -> + !innerDescriptor.isCallableMemberWithJvmDefaultAnnotation(state.jvmDefaultMode) -> OwnerKind.DEFAULT_IMPLS else -> OwnerKind.IMPLEMENTATION diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt index 368f616586f..9a2d644be2a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt @@ -54,6 +54,7 @@ class JvmSerializerExtension @JvmOverloads constructor( private val isParamAssertionsDisabled = state.isParamAssertionsDisabled private val unifiedNullChecks = state.unifiedNullChecks override val metadataVersion = state.metadataVersion + private val jvmDefaultMode = state.jvmDefaultMode override fun shouldUseTypeTable(): Boolean = useTypeTable override fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean { @@ -98,7 +99,7 @@ class JvmSerializerExtension @JvmOverloads constructor( if ( isInterface(classDescriptor) && classDescriptor.unsubstitutedMemberScope.getContributedDescriptors().any { - it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation() + it is CallableMemberDescriptor && it.hasJvmDefaultAnnotation(jvmDefaultMode) //TODO: new requirements for new option } ) { builder.addVersionRequirement( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index e64acd765f4..dc87400a459 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -21,10 +21,7 @@ import org.jetbrains.kotlin.codegen.inline.FictitiousArrayConstructor import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter -import org.jetbrains.kotlin.config.JvmTarget -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil @@ -89,6 +86,7 @@ class KotlinTypeMapper @JvmOverloads constructor( private val namePreprocessor: ((ClassDescriptor) -> String?)? = null ) : KotlinTypeMapperBase() { private val isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) + val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode) private val typeMappingConfiguration = object : TypeMappingConfiguration { override fun commonSupertype(types: Collection): KotlinType { @@ -424,7 +422,7 @@ class KotlinTypeMapper @JvmOverloads constructor( val functionParent = descriptor.original.containingDeclaration - var functionDescriptor = findSuperDeclaration(descriptor.original, superCall) + var functionDescriptor = findSuperDeclaration(descriptor.original, superCall, jvmDefaultMode) val signature: JvmMethodSignature val returnKotlinType: KotlinType? @@ -449,8 +447,8 @@ class KotlinTypeMapper @JvmOverloads constructor( baseMethodDescriptor = findBaseDeclaration(functionDescriptor).original val ownerForDefault = baseMethodDescriptor.containingDeclaration as ClassDescriptor - isDefaultMethodInInterface = isJvmInterface(ownerForDefault) && baseMethodDescriptor.hasJvmDefaultAnnotation() - ownerForDefaultImpl = if (isJvmInterface(ownerForDefault) && !baseMethodDescriptor.hasJvmDefaultAnnotation()) + isDefaultMethodInInterface = isJvmInterface(ownerForDefault) && baseMethodDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode) + ownerForDefaultImpl = if (isJvmInterface(ownerForDefault) && !baseMethodDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode)) mapDefaultImpls(ownerForDefault) else mapClass(ownerForDefault) @@ -458,7 +456,7 @@ class KotlinTypeMapper @JvmOverloads constructor( if (isInterface && (superCall || descriptor.visibility == Visibilities.PRIVATE || isAccessor(descriptor))) { thisClass = mapClass(functionParent) dispatchReceiverKotlinType = functionParent.defaultType - if (declarationOwner is JavaClassDescriptor || declarationFunctionDescriptor.hasJvmDefaultAnnotation()) { + if (declarationOwner is JavaClassDescriptor || declarationFunctionDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode)) { invokeOpcode = INVOKESPECIAL signature = mapSignatureSkipGeneric(functionDescriptor) returnKotlinType = functionDescriptor.returnType @@ -469,7 +467,7 @@ class KotlinTypeMapper @JvmOverloads constructor( val originalDescriptor = descriptor.original signature = mapSignatureSkipGeneric(originalDescriptor, OwnerKind.DEFAULT_IMPLS) returnKotlinType = getReturnValueType(originalDescriptor) - if (descriptor is AccessorForCallableDescriptor<*> && descriptor.calleeDescriptor.hasJvmDefaultAnnotation()) { + if (descriptor is AccessorForCallableDescriptor<*> && descriptor.calleeDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode)) { owner = mapClass(functionParent) isInterfaceMember = true } else { @@ -1510,7 +1508,7 @@ class KotlinTypeMapper @JvmOverloads constructor( } //NB: similar platform agnostic code in DescriptorUtils.unwrapFakeOverride - private fun findSuperDeclaration(descriptor: FunctionDescriptor, isSuperCall: Boolean): FunctionDescriptor { + private fun findSuperDeclaration(descriptor: FunctionDescriptor, isSuperCall: Boolean, jvmDefaultMode: JvmDefaultMode): FunctionDescriptor { var current = descriptor while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { val classCallable = current.overriddenDescriptors.firstOrNull { !isInterface(it.containingDeclaration) } @@ -1519,7 +1517,7 @@ class KotlinTypeMapper @JvmOverloads constructor( current = classCallable continue } - if (isSuperCall && !current.hasJvmDefaultAnnotation() && !isInterface(current.containingDeclaration)) { + if (isSuperCall && !current.hasJvmDefaultAnnotation(jvmDefaultMode) && !isInterface(current.containingDeclaration)) { //Don't unwrap fake overrides from class to interface cause substituted override would be implicitly generated return current } diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmDefaultMode.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmDefaultMode.kt index 300b3fd85e1..72b0d768be5 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmDefaultMode.kt +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmDefaultMode.kt @@ -8,13 +8,18 @@ package org.jetbrains.kotlin.config enum class JvmDefaultMode(val description: String) { DISABLE("disable"), ENABLE("enable"), - ENABLE_WITH_DEFAULT_IMPLS("compatibility"); + ENABLE_WITH_DEFAULT_IMPLS("compatibility"), + ALL_COMPATIBILITY("all-compatibility"), + ALL_INCOMPATIBLE("all"); val isEnabled get() = this != DISABLE val isCompatibility - get() = this == ENABLE_WITH_DEFAULT_IMPLS + get() = this == ENABLE_WITH_DEFAULT_IMPLS || this == ALL_COMPATIBILITY + + val forAllMehtodsWithBody + get() = this == ALL_COMPATIBILITY || this == ALL_INCOMPATIBLE companion object { @JvmField diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt index 646c55ce014..64aadb0e1df 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmDelegationFilter.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.jvm import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor @@ -35,7 +36,7 @@ object JvmDelegationFilter : DelegationFilter { //We always have only one implementation otherwise it's an error in kotlin and java val realMember = DescriptorUtils.unwrapFakeOverride(interfaceMember) return !isJavaDefaultMethod(realMember) && - !realMember.hasJvmDefaultAnnotation() && + !realMember.hasJvmDefaultAnnotation(languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)) && !isBuiltInMemberMappedToJavaDefault(realMember) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt index cd53f7b5349..76acb45a583 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotations/jvmAnnotationUtil.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.jvm.annotations +import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor @@ -40,11 +41,11 @@ fun DeclarationDescriptor.findJvmFieldAnnotation(): AnnotationDescriptor? = fun DeclarationDescriptor.hasJvmFieldAnnotation(): Boolean = findJvmFieldAnnotation() != null -fun DeclarationDescriptor.isCallableMemberWithJvmDefaultAnnotation(): Boolean = - this is CallableMemberDescriptor && hasJvmDefaultAnnotation() +fun DeclarationDescriptor.isCallableMemberWithJvmDefaultAnnotation(jvmDefault: JvmDefaultMode): Boolean = + this is CallableMemberDescriptor && hasJvmDefaultAnnotation(jvmDefault) -fun CallableMemberDescriptor.hasJvmDefaultAnnotation(): Boolean = - DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) +fun CallableMemberDescriptor.hasJvmDefaultAnnotation(jvmDefault: JvmDefaultMode): Boolean = + jvmDefault.forAllMehtodsWithBody || DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) fun CallableMemberDescriptor.hasPlatformDependentAnnotation(): Boolean = DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt index 9f8fcdfaaa8..bb819827787 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/InterfaceDefaultMethodCallChecker.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor @@ -61,13 +62,14 @@ class InterfaceDefaultMethodCallChecker(val jvmTarget: JvmTarget) : CallChecker val realDescriptor = unwrapFakeOverride(descriptor) val realDescriptorOwner = realDescriptor.containingDeclaration as? ClassDescriptor ?: return - if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor || realDescriptor.hasJvmDefaultAnnotation())) { + val jvmDefaultMode = context.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode) + if (isInterface(realDescriptorOwner) && (realDescriptor is JavaCallableMemberDescriptor || realDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode))) { val bindingContext = context.trace.bindingContext val thisForSuperCall = getSuperCallLabelTarget(bindingContext, superCallExpression) if (thisForSuperCall != null && DescriptorUtils.isInterface(thisForSuperCall)) { val declarationWithCall = findInterfaceMember(thisForSuperCall, superCallExpression, bindingContext) - if (declarationWithCall?.hasJvmDefaultAnnotation() == false) { + if (declarationWithCall?.hasJvmDefaultAnnotation(jvmDefaultMode) == false) { context.trace.report(INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER.on(reportOn)) return } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmDefaultChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmDefaultChecker.kt index 31d13199bba..2175f5a2d08 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmDefaultChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmDefaultChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.resolve.jvm.checkers import org.jetbrains.kotlin.config.JvmAnalysisFlags +import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor @@ -40,9 +41,9 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker { if (descriptor is ClassDescriptor) { val hasDeclaredJvmDefaults = descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance().any { - it.kind.isReal && it.hasJvmDefaultAnnotation() + it.kind.isReal && it.hasJvmDefaultAnnotation(jvmDefaultMode) } - if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, jvmDefaultMode.isEnabled)) { + if (!hasDeclaredJvmDefaults && !checkJvmDefaultsInHierarchy(descriptor, jvmDefaultMode)) { context.trace.report(ErrorsJvm.JVM_DEFAULT_THROUGH_INHERITANCE.on(declaration)) } } @@ -65,15 +66,15 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker { } } - private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, enableJvmDefault: Boolean): Boolean { - if (enableJvmDefault) return true + private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, jvmDefaultMode: JvmDefaultMode): Boolean { + if (jvmDefaultMode.isEnabled) return true if (descriptor !is ClassDescriptor) return true return descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance() .all { memberDescriptor -> memberDescriptor.kind.isReal || OverridingUtil.filterOutOverridden(memberDescriptor.overriddenDescriptors.toSet()).all { - !isInterface(it.containingDeclaration) || !it.hasJvmDefaultAnnotation() || it.modality == Modality.ABSTRACT + !isInterface(it.containingDeclaration) || !it.hasJvmDefaultAnnotation(jvmDefaultMode) || it.modality == Modality.ABSTRACT } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmDefaultSuperCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmDefaultSuperCallChecker.kt index 443b856c529..d56439db548 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmDefaultSuperCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmDefaultSuperCallChecker.kt @@ -23,7 +23,7 @@ class JvmDefaultSuperCallChecker : CallChecker { if (getSuperCallExpression(resolvedCall.call) == null) return val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return - if (!resultingDescriptor.hasJvmDefaultAnnotation()) return + if (!resultingDescriptor.hasJvmDefaultAnnotation(jvmDefaultMode)) return if (DescriptorUtils.isInterface(resultingDescriptor.containingDeclaration)) { context.trace.report(ErrorsJvm.USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL.on(reportOn)) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index 3253b70738c..09bfe23c479 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -248,7 +248,12 @@ private fun KtUltraLightClass.lightMethod( val name = if (descriptor is ConstructorDescriptor) name else support.typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION) val accessFlags: Int by lazyPub { - val asmFlags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, support.deprecationResolver) + val asmFlags = AsmUtil.getMethodAsmFlags( + descriptor, + OwnerKind.IMPLEMENTATION, + support.deprecationResolver, + support.typeMapper.jvmDefaultMode, + ) packMethodFlags(asmFlags, JvmCodegenUtil.isJvmInterface(kotlinOrigin.resolve() as? ClassDescriptor)) }