[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
).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.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.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.getInlinedClass
import org.jetbrains.kotlin.ir.util.isInlined
import org.jetbrains.kotlin.ir.util.isNullable
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.*
// Copied and adapted from Kotlin/Native
@@ -34,10 +33,11 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
val actualType = when (this) {
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
} else {
this.symbol.owner.returnType
function.realOverrideTarget.returnType
}
}
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 {
return this.useAs(
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.ir.backend.js.utils.JsGenerationContext
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.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
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.util.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -121,7 +121,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
}
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 {
return it(expression, context)
@@ -143,13 +144,13 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
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
// initialize underlying property.
// TODO: Support initialization block
val klass = symbol.owner.parentAsClass
val klass = function.parentAsClass
if (klass.isInline) {
assert(symbol.owner.isPrimary) {
assert(function.isPrimary) {
"Inline class secondary constructors must be lowered into static methods"
}
// 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.ir.backend.js.utils.JsGenerationContext
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.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -105,7 +106,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
return translatedFunction?.makeStmt()
}
val memberName = context.getNameForSymbol(declaration.symbol)
val memberName = context.getNameForSymbol(declaration.realOverrideTarget.symbol)
val memberRef = JsNameRef(memberName, classPrototypeRef)
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
// II.prototype.foo = I.prototype.foo
if (!irClass.isInterface) {
declaration.resolveFakeOverride()?.let {
declaration.realOverrideTarget.let { it ->
var implClassDeclaration = it.parent as IrClass
// 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.impl.IrCallImpl
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.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -291,11 +287,8 @@ fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
return this.hasAncestorInSuperTypes()
}
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
if (isReal) return this
fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
if (isReal) return setOf(this)
val visited = mutableSetOf<IrSimpleFunction>()
val realOverrides = mutableSetOf<IrSimpleFunction>()
@@ -324,7 +317,13 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
visited.clear()
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? {