JVM IR: Do not generate DefaultImpls if it's empty. This revealed that InterfaceDelegationLowering was relying on the presence of DefaultImpls even when empty. Hence, simply dropping it from InterfaceLowering was not trivial. Moved default delegation in DefaultImpls to SuperType.DefaultImpls to InterfaceLowering. Clean up logic considerably, and document inter-phase dependencies.
This commit is contained in:
committed by
max-kammerer
parent
cc6252098f
commit
9d1d6a7b1f
@@ -144,6 +144,13 @@ private val defaultArgumentInjectorPhase = makeIrFilePhase(
|
||||
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase)
|
||||
)
|
||||
|
||||
private val interfacePhase = makeIrFilePhase(
|
||||
::InterfaceLowering,
|
||||
name = "Interface",
|
||||
description = "Move default implementations of interface members to DefaultImpls class",
|
||||
prerequisite = setOf(defaultArgumentInjectorPhase)
|
||||
)
|
||||
|
||||
private val innerClassesPhase = makeIrFilePhase(
|
||||
::InnerClassesLowering,
|
||||
name = "InnerClasses",
|
||||
@@ -158,6 +165,13 @@ private val returnableBlocksPhase = makeIrFilePhase(
|
||||
prerequisite = setOf(arrayConstructorPhase, assertionPhase)
|
||||
)
|
||||
|
||||
private val syntheticAccessorPhase = makeIrFilePhase(
|
||||
::SyntheticAccessorLowering,
|
||||
name = "SyntheticAccessor",
|
||||
description = "Introduce synthetic accessors",
|
||||
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
|
||||
)
|
||||
|
||||
@Suppress("Reformat")
|
||||
private val jvmFilePhases =
|
||||
typeAliasAnnotationMethodsPhase then
|
||||
|
||||
+52
-68
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -39,7 +38,6 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.function.UnaryOperator
|
||||
|
||||
internal val interfaceDelegationPhase = makeIrFilePhase(
|
||||
::InterfaceDelegationLowering,
|
||||
@@ -68,95 +66,80 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
}
|
||||
|
||||
private fun generateInterfaceMethods(irClass: IrClass) {
|
||||
val (actualClass, isDefaultImplsGeneration) = if (irClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) {
|
||||
Pair(irClass.parent as IrClass, true)
|
||||
} else {
|
||||
Pair(irClass, false)
|
||||
}
|
||||
|
||||
val toRemove = mutableListOf<IrSimpleFunction>()
|
||||
for (function in actualClass.functions.toList()) { // Copy the list, because we are adding new declarations from the loop
|
||||
for (function in irClass.functions.toList()) { // Copy the list, because we are adding new declarations from the loop
|
||||
if (function.origin !== IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
||||
|
||||
// In classes, only generate interface delegation for functions immediately inherited from an interface.
|
||||
// Only generate interface delegation for functions immediately inherited from an interface.
|
||||
// (Otherwise, delegation will be present in the parent class)
|
||||
if (!isDefaultImplsGeneration &&
|
||||
function.overriddenSymbols.any {
|
||||
(!it.owner.parentAsClass.isInterface || it.owner.hasJvmDefault()) &&
|
||||
it.owner.modality != Modality.ABSTRACT
|
||||
}
|
||||
) {
|
||||
if (function.overriddenSymbols.any { !it.owner.parentAsClass.isInterface && it.owner.modality != Modality.ABSTRACT }) {
|
||||
continue
|
||||
}
|
||||
|
||||
val implementation = function.resolveFakeOverride() ?: continue
|
||||
if (!implementation.hasInterfaceParent() ||
|
||||
Visibilities.isPrivate(implementation.visibility) ||
|
||||
implementation.isDefinitelyNotDefaultImplsMethod() ||
|
||||
implementation.isMethodOfAny() ||
|
||||
(!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault())
|
||||
|
||||
if (!implementation.hasInterfaceParent()
|
||||
|| Visibilities.isPrivate(implementation.visibility)
|
||||
|| implementation.isDefinitelyNotDefaultImplsMethod()
|
||||
|| implementation.isMethodOfAny()
|
||||
|| (!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault())
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
val delegation = generateDelegationToDefaultImpl(irClass, implementation, function, isDefaultImplsGeneration)
|
||||
if (!isDefaultImplsGeneration) {
|
||||
toRemove.add(function)
|
||||
replacementMap[function.symbol] = delegation.symbol
|
||||
}
|
||||
toRemove.add(function)
|
||||
|
||||
val delegation = generateDelegationToDefaultImpl(irClass, implementation, function)
|
||||
irClass.declarations.add(delegation)
|
||||
replacementMap[function.symbol] = delegation.symbol
|
||||
}
|
||||
irClass.declarations.removeAll(toRemove)
|
||||
}
|
||||
|
||||
private fun generateDelegationToDefaultImpl(
|
||||
irClass: IrClass,
|
||||
interfaceFun: IrSimpleFunction,
|
||||
inheritedFun: IrSimpleFunction,
|
||||
isDefaultImplsGeneration: Boolean
|
||||
interfaceImplementation: IrSimpleFunction,
|
||||
classOverride: IrSimpleFunction
|
||||
): IrSimpleFunction {
|
||||
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceFun)
|
||||
val inheritedProperty = classOverride.correspondingPropertySymbol?.owner
|
||||
val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(classOverride.descriptor)
|
||||
|
||||
val irFunction =
|
||||
if (!isDefaultImplsGeneration) {
|
||||
val inheritedProperty = inheritedFun.correspondingPropertySymbol?.owner
|
||||
val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(inheritedFun.descriptor)
|
||||
IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
inheritedFun.name,
|
||||
Visibilities.PUBLIC,
|
||||
inheritedFun.modality,
|
||||
inheritedFun.returnType,
|
||||
isInline = inheritedFun.isInline,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = inheritedFun.isSuspend
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = irClass
|
||||
overriddenSymbols.addAll(inheritedFun.overriddenSymbols)
|
||||
copyParameterDeclarationsFrom(inheritedFun)
|
||||
annotations.addAll(inheritedFun.annotations)
|
||||
IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
classOverride.name,
|
||||
Visibilities.PUBLIC,
|
||||
classOverride.modality,
|
||||
classOverride.returnType,
|
||||
isInline = classOverride.isInline,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = classOverride.isSuspend
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = irClass
|
||||
overriddenSymbols.addAll(classOverride.overriddenSymbols)
|
||||
copyParameterDeclarationsFrom(classOverride)
|
||||
annotations.addAll(classOverride.annotations)
|
||||
|
||||
if (inheritedProperty != null) {
|
||||
val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor)
|
||||
IrPropertyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor),
|
||||
inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar,
|
||||
inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false
|
||||
).apply {
|
||||
propertyDescriptor.bind(this)
|
||||
parent = irClass
|
||||
correspondingPropertySymbol = symbol
|
||||
}
|
||||
if (inheritedProperty != null) {
|
||||
val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor)
|
||||
IrPropertyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor),
|
||||
inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar,
|
||||
inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false
|
||||
).apply {
|
||||
propertyDescriptor.bind(this)
|
||||
parent = irClass
|
||||
correspondingPropertySymbol = symbol
|
||||
}
|
||||
}
|
||||
} else context.declarationFactory.getDefaultImplsFunction(inheritedFun)
|
||||
|
||||
irClass.declarations.add(irFunction)
|
||||
}
|
||||
|
||||
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceImplementation)
|
||||
context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply {
|
||||
irFunction.body = irBlockBody {
|
||||
+irReturn(
|
||||
@@ -182,7 +165,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
declaration.overriddenSymbols.replaceAll(UnaryOperator { symbol -> replacementMap[symbol] ?: symbol })
|
||||
declaration.overriddenSymbols.replaceAll { symbol -> replacementMap[symbol] ?: symbol }
|
||||
super.visitSimpleFunction(declaration)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +217,8 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
||||
val callee = expression.symbol.owner
|
||||
|
||||
if (callee.parent.safeAs<IrClass>()?.isInterface != true ||
|
||||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
(callee.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility)
|
||||
) {
|
||||
return super.visitCall(expression)
|
||||
}
|
||||
|
||||
+99
-41
@@ -7,14 +7,17 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyBodyToStatic
|
||||
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
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.ir.hasJvmDefault
|
||||
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.irBlockBody
|
||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
@@ -23,62 +26,95 @@ import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal val interfacePhase = makeIrFilePhase(
|
||||
::InterfaceLowering,
|
||||
name = "Interface",
|
||||
description = "Move default implementations of interface members to DefaultImpls class"
|
||||
)
|
||||
/**
|
||||
* This phase moves interface members with default implementations to the
|
||||
* associated companion DefaultImpls with bridges, as appropriate. It then
|
||||
* performs a traversal of any other code in this interface and redirects calls
|
||||
* to the interface to the companion, if functions were moved completely.
|
||||
*/
|
||||
internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
|
||||
private class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
|
||||
val state = context.state
|
||||
val removedFunctions = hashMapOf<IrFunctionSymbol, IrFunctionSymbol>()
|
||||
private val removedFunctions = hashMapOf<IrFunctionSymbol, IrFunctionSymbol>()
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (!irClass.isInterface) return
|
||||
|
||||
val defaultImplsIrClass = context.declarationFactory.getDefaultImplsClass(irClass)
|
||||
//TODO: Don't add DefaultImpls if it's empty. Just like the old backend...?
|
||||
irClass.declarations.add(defaultImplsIrClass)
|
||||
val members = defaultImplsIrClass.declarations
|
||||
|
||||
for (function in irClass.declarations) {
|
||||
if (function !is IrSimpleFunction) continue
|
||||
// There are 6 cases for functions on interfaces:
|
||||
loop@ for (function in irClass.functions) {
|
||||
when {
|
||||
/**
|
||||
* 1) They are plain abstract interface functions, in which case we leave them:
|
||||
*/
|
||||
function.modality == Modality.ABSTRACT ->
|
||||
continue@loop
|
||||
|
||||
if (function.modality != Modality.ABSTRACT && function.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||
/**
|
||||
* 2) They inherit a default implementation from an interface this interface
|
||||
* extends: create a bridge from companion to companion, if necessary:
|
||||
*
|
||||
* ```
|
||||
* interface A { fun foo() = 0 }
|
||||
* interface B : A { }
|
||||
* ```
|
||||
*
|
||||
* yields
|
||||
*
|
||||
* ```
|
||||
* interface A { fun foo(); class DefaultImpls { fun foo() = 0 } } // !! by Case 4 !!
|
||||
* interface B : A { class DefaultImpls { fun foo() = A.DefaultImpls.foo() } }
|
||||
* ```
|
||||
*/
|
||||
function.origin == IrDeclarationOrigin.FAKE_OVERRIDE -> {
|
||||
val implementation = function.resolveFakeOverride()!!
|
||||
|
||||
if(function.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility && !mustMoveToDefaultImpls(function)) continue
|
||||
|
||||
val element = context.declarationFactory.getDefaultImplsFunction(function).also {
|
||||
if (mustMoveToDefaultImpls(function))
|
||||
removedFunctions[function.symbol] = it.symbol
|
||||
if (!Visibilities.isPrivate(implementation.visibility)
|
||||
&& !implementation.isMethodOfAny()
|
||||
&& (!implementation.hasJvmDefault() || context.state.jvmDefaultMode.isCompatibility)
|
||||
) {
|
||||
delegateInheritedDefaultImplementationToDefaultImpls(function, implementation, defaultImplsIrClass)
|
||||
}
|
||||
}
|
||||
members.add(element)
|
||||
|
||||
copyBodyToStatic(function, element)
|
||||
element.body = element.body?.patchDeclarationParents(element)
|
||||
/**
|
||||
* 3) Private methods, default parameter dispatchers (without @JvmDefault)
|
||||
* and $annotation methods are always moved without bridges
|
||||
*/
|
||||
Visibilities.isPrivate(function.visibility)
|
||||
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault())
|
||||
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> {
|
||||
val defaultImpl = createDefaultImpl(function, members)
|
||||
removedFunctions[function.symbol] = defaultImpl.symbol
|
||||
}
|
||||
|
||||
if (function.hasJvmDefault() &&
|
||||
function.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
|
||||
) {
|
||||
function.body = IrExpressionBodyImpl(callDefaultImpls(element, function))
|
||||
} else {
|
||||
/**
|
||||
* 4) _Without_ @JvmDefault, the default implementation is moved to DefaultImpls and
|
||||
* an abstract stub is left.
|
||||
*/
|
||||
!function.hasJvmDefault() -> {
|
||||
createDefaultImpl(function, members)
|
||||
function.body = null
|
||||
//TODO reset modality to abstract
|
||||
}
|
||||
|
||||
/**
|
||||
* 5) _With_ @JvmDefault, we move and bridge if in compatibility mode, ...
|
||||
*/
|
||||
context.state.jvmDefaultMode.isCompatibility -> {
|
||||
val defaultImpl = createDefaultImpl(function, members)
|
||||
function.body = IrExpressionBodyImpl(createDelegatingCall(defaultImpl, function))
|
||||
}
|
||||
|
||||
// 6) ... otherwise we simply leave the default function implementation on the interface.
|
||||
}
|
||||
}
|
||||
|
||||
// Update IrElements (e.g., IrCalls) to point to the new functions.
|
||||
irClass.transformChildrenVoid(this)
|
||||
|
||||
irClass.declarations.removeAll {
|
||||
it is IrFunction && removedFunctions.containsKey(it.symbol)
|
||||
}
|
||||
@@ -99,14 +135,20 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
|
||||
delegatedPropertyArray.parent = defaultImplsIrClass
|
||||
delegatedPropertyArray.initializer?.patchDeclarationParents(defaultImplsIrClass)
|
||||
}
|
||||
|
||||
if (defaultImplsIrClass.declarations.isNotEmpty()) irClass.declarations.add(defaultImplsIrClass)
|
||||
// Update IrElements (e.g., IrCalls) to point to the new functions.
|
||||
irClass.transformChildrenVoid(this)
|
||||
}
|
||||
|
||||
private fun mustMoveToDefaultImpls(function: IrFunction): Boolean =
|
||||
Visibilities.isPrivate(function.visibility) && function.name != clinitName ||
|
||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
|
||||
private fun createDefaultImpl(function: IrSimpleFunction, members: MutableList<IrDeclaration>): IrSimpleFunction =
|
||||
context.declarationFactory.getDefaultImplsFunction(function).also {
|
||||
it.body = function.body?.patchDeclarationParents(it)
|
||||
copyBodyToStatic(function, it)
|
||||
members.add(it)
|
||||
}
|
||||
|
||||
private fun callDefaultImpls(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrCall {
|
||||
private fun createDelegatingCall(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrCall {
|
||||
val startOffset = interfaceMethod.startOffset
|
||||
val endOffset = interfaceMethod.endOffset
|
||||
|
||||
@@ -126,6 +168,22 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
|
||||
}
|
||||
}
|
||||
|
||||
private fun delegateInheritedDefaultImplementationToDefaultImpls(
|
||||
fakeOverride: IrSimpleFunction,
|
||||
implementation: IrSimpleFunction,
|
||||
defaultImpls: IrClass
|
||||
) {
|
||||
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(implementation)
|
||||
val irFunction = context.declarationFactory.getDefaultImplsFunction(fakeOverride)
|
||||
|
||||
defaultImpls.declarations.add(irFunction)
|
||||
context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply {
|
||||
irFunction.body = irBlockBody {
|
||||
+irReturn(createDelegatingCall(defaultImplFun, irFunction))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
val newFunction = removedFunctions[expression.returnTargetSymbol]?.owner
|
||||
return super.visitReturn(
|
||||
|
||||
+1
-8
@@ -36,14 +36,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal val syntheticAccessorPhase = makeIrFilePhase(
|
||||
::SyntheticAccessorLowering,
|
||||
name = "SyntheticAccessor",
|
||||
description = "Introduce synthetic accessors",
|
||||
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase)
|
||||
)
|
||||
|
||||
private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||
internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||
private val pendingTransformations = mutableListOf<Function0<Unit>>()
|
||||
private val inlineLambdaToCallSite = mutableMapOf<IrFunction, IrDeclaration?>()
|
||||
|
||||
|
||||
@@ -11,12 +11,10 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.name
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface A {
|
||||
@JvmDefault
|
||||
fun foo(x: Int = 0): Int {
|
||||
return x
|
||||
}
|
||||
}
|
||||
|
||||
// TESTED_OBJECT_KIND: innerClass
|
||||
// TESTED_OBJECTS: A, DefaultImpls
|
||||
// FLAGS: ACC_FINAL, ACC_STATIC, ACC_PUBLIC
|
||||
|
||||
// TESTED_OBJECT_KIND: function
|
||||
// TESTED_OBJECTS: A, foo$default
|
||||
// FLAGS: ACC_PUBLIC, ACC_SYNTHETIC, ACC_STATIC
|
||||
|
||||
// TESTED_OBJECT_KIND: function
|
||||
// TESTED_OBJECTS: A$DefaultImpls, foo$default
|
||||
// FLAGS: ACC_PUBLIC, ACC_SYNTHETIC, ACC_STATIC
|
||||
@@ -0,0 +1,20 @@
|
||||
// !JVM_DEFAULT_MODE: enable
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface Test {
|
||||
@JvmDefault
|
||||
fun foo(): String {
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@JvmDefault
|
||||
fun bar(x: String = "OK"): String {
|
||||
return x
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TESTED_OBJECT_KIND: innerClass
|
||||
// TESTED_OBJECTS: Test, DefaultImpls
|
||||
// ABSENT: TRUE
|
||||
+10
@@ -756,6 +756,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("onlyJvmDefaultsOnInterface.kt")
|
||||
public void testOnlyJvmDefaultsOnInterface() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAnnotation.kt")
|
||||
public void testPropertyAnnotation() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt");
|
||||
@@ -773,6 +778,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/jvm8/defaults/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultImplementations.kt")
|
||||
public void testDefaultImplementations() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt");
|
||||
|
||||
+10
@@ -756,6 +756,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("onlyJvmDefaultsOnInterface.kt")
|
||||
public void testOnlyJvmDefaultsOnInterface() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAnnotation.kt")
|
||||
public void testPropertyAnnotation() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt");
|
||||
@@ -773,6 +778,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/jvm8/defaults/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultImplementations.kt")
|
||||
public void testDefaultImplementations() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt");
|
||||
|
||||
Reference in New Issue
Block a user