[JS IR BE] Fix fake override functions resolve

Use signature of function 'target' (a real function that will
be called instad of fake override) to make boxing/unboxing decision for
return value and type parameters on call site.
This commit is contained in:
Svyatoslav Kuzmich
2018-12-05 14:08:16 +03:00
parent 08abf5f2a2
commit ebdbe7ec30
6 changed files with 80 additions and 23 deletions
@@ -360,3 +360,5 @@ fun Scope.createTemporaryVariableWithWrappedDescriptor(
irExpression, nameHint, isMutable, origin, descriptor irExpression, nameHint, isMutable, origin, descriptor
).apply { descriptor.bind(this) } ).apply { descriptor.bind(this) }
} }
val IrFunction.isOverridable: Boolean get() = this is IrSimpleFunction && this.isOverridable
@@ -7,17 +7,16 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.AbstractValueUsageTransformer import org.jetbrains.kotlin.backend.common.lower.AbstractValueUsageTransformer
import org.jetbrains.kotlin.backend.common.utils.isPrimitiveArray
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.getInlinedClass import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.isInlined
import org.jetbrains.kotlin.ir.util.isNullable
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
// Copied and adapted from Kotlin/Native // Copied and adapted from Kotlin/Native
@@ -34,10 +33,11 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
val actualType = when (this) { val actualType = when (this) {
is IrCall -> { is IrCall -> {
if (this.symbol.owner.let { it is IrSimpleFunction && it.isSuspend }) { val function = this.symbol.owner
if (function.let { it is IrSimpleFunction && it.isSuspend }) {
irBuiltIns.anyNType irBuiltIns.anyNType
} else { } else {
this.symbol.owner.returnType function.realOverrideTarget.returnType
} }
} }
is IrGetField -> this.symbol.owner.type is IrGetField -> this.symbol.owner.type
@@ -121,6 +121,34 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
} }
} }
private val IrFunctionAccessExpression.target: IrFunction
get() = when (this) {
is IrCall -> this.callTarget
is IrDelegatingConstructorCall -> this.symbol.owner
else -> TODO(this.render())
}
private val IrCall.callTarget: IrFunction
get() = symbol.owner.realOverrideTarget
override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression {
return this.useAsArgument(expression.target.dispatchReceiverParameter!!)
}
override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression {
return this.useAsArgument(expression.target.extensionReceiverParameter!!)
}
override fun IrExpression.useAsValueArgument(
expression: IrFunctionAccessExpression,
parameter: IrValueParameter
): IrExpression {
return this.useAsArgument(expression.target.valueParameters[parameter.index])
}
override fun IrExpression.useAsVarargElement(expression: IrVararg): IrExpression { override fun IrExpression.useAsVarargElement(expression: IrVararg): IrExpression {
return this.useAs( return this.useAs(
if (this.type.isInlined()) if (this.type.isInlined())
@@ -141,3 +169,4 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
} }
} }
@@ -8,11 +8,11 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -121,7 +121,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
} }
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression { override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
val symbol = expression.symbol val function = expression.symbol.owner.realOverrideTarget
val symbol = function.symbol
context.staticContext.intrinsics[symbol]?.let { context.staticContext.intrinsics[symbol]?.let {
return it(expression, context) return it(expression, context)
@@ -143,13 +144,13 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
return JsInvocation(callRef, jsDispatchReceiver?.let { listOf(it) + arguments } ?: arguments) return JsInvocation(callRef, jsDispatchReceiver?.let { listOf(it) + arguments } ?: arguments)
} }
return if (symbol is IrConstructorSymbol) { return if (function is IrConstructor) {
// Inline class primary constructor takes a single value of to // Inline class primary constructor takes a single value of to
// initialize underlying property. // initialize underlying property.
// TODO: Support initialization block // TODO: Support initialization block
val klass = symbol.owner.parentAsClass val klass = function.parentAsClass
if (klass.isInline) { if (klass.isInline) {
assert(symbol.owner.isPrimary) { assert(function.isPrimary) {
"Inline class secondary constructors must be lowered into static methods" "Inline class secondary constructors must be lowered into static methods"
} }
// Argument value constructs unboxed inline class instance // Argument value constructs unboxed inline class instance
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.onlyIf
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -105,7 +106,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
return translatedFunction?.makeStmt() return translatedFunction?.makeStmt()
} }
val memberName = context.getNameForSymbol(declaration.symbol) val memberName = context.getNameForSymbol(declaration.realOverrideTarget.symbol)
val memberRef = JsNameRef(memberName, classPrototypeRef) val memberRef = JsNameRef(memberName, classPrototypeRef)
translatedFunction?.let { return jsAssignment(memberRef, it.apply { name = null }).makeStmt() } translatedFunction?.let { return jsAssignment(memberRef, it.apply { name = null }).makeStmt() }
@@ -115,7 +116,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
// interface II : I // interface II : I
// II.prototype.foo = I.prototype.foo // II.prototype.foo = I.prototype.foo
if (!irClass.isInterface) { if (!irClass.isInterface) {
declaration.resolveFakeOverride()?.let { declaration.realOverrideTarget.let { it ->
var implClassDeclaration = it.parent as IrClass var implClassDeclaration = it.parent as IrClass
// special case // special case
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.collectRealOverrides
val IrFunction.realOverrideTarget: IrFunction
get() = when (this) {
is IrSimpleFunction -> this.realOverrideTarget
is IrConstructor -> this
else -> error(this)
}
val IrSimpleFunction.realOverrideTarget: IrSimpleFunction
get(): IrSimpleFunction {
val realOverrides = collectRealOverrides()
return realOverrides.find { it.modality != Modality.ABSTRACT } ?: realOverrides.first()
}
@@ -17,11 +17,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -291,11 +287,8 @@ fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
return this.hasAncestorInSuperTypes() return this.hasAncestorInSuperTypes()
} }
// This implementation is from kotlin-native fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
// TODO: use this implementation instead of any other if (isReal) return setOf(this)
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
if (isReal) return this
val visited = mutableSetOf<IrSimpleFunction>() val visited = mutableSetOf<IrSimpleFunction>()
val realOverrides = mutableSetOf<IrSimpleFunction>() val realOverrides = mutableSetOf<IrSimpleFunction>()
@@ -324,7 +317,13 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
visited.clear() visited.clear()
realOverrides.toList().forEach { excludeRepeated(it) } realOverrides.toList().forEach { excludeRepeated(it) }
return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT } return realOverrides
}
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
return collectRealOverrides().singleOrNull { it.modality != Modality.ABSTRACT }
} }
fun IrField.resolveFakeOverride(): IrField? { fun IrField.resolveFakeOverride(): IrField? {