[JS IR BE] Make kotlinx.io compile
- Fix expect/actual default arguments - Fix dynamic type in inliner - Fix external varargs
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.util.ExpectDeclarationRemover
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
/**
|
||||
* This pass removes all declarations with `isExpect == true`.
|
||||
*/
|
||||
class ExpectDeclarationsRemoveLowering(val context: BackendContext) : FileLoweringPass {
|
||||
|
||||
val visitor = ExpectDeclarationRemover(context.ir.symbols.externalSymbolTable, true)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.acceptVoid(visitor)
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ private val moveBodilessDeclarationsToSeparatePlacePhase = makeCustomJsModulePha
|
||||
)
|
||||
|
||||
private val expectDeclarationsRemovingPhase = makeJsModulePhase(
|
||||
::ExpectDeclarationsRemoving,
|
||||
::ExpectDeclarationsRemoveLowering,
|
||||
name = "ExpectDeclarationsRemoving",
|
||||
description = "Remove expect declaration from module fragment"
|
||||
)
|
||||
|
||||
+4
-2
@@ -157,8 +157,10 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
|
||||
if (type !is IrSimpleType) return type
|
||||
|
||||
val substitutedType = typeArguments?.get(type.classifier)
|
||||
if (substitutedType != null) {
|
||||
substitutedType as IrSimpleType
|
||||
|
||||
if (substitutedType is IrDynamicType) return substitutedType
|
||||
|
||||
if (substitutedType is IrSimpleType) {
|
||||
return substitutedType.buildSimpleType {
|
||||
kotlinType = null
|
||||
hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable()
|
||||
|
||||
+4
-1
@@ -282,6 +282,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
JsInvocation(
|
||||
// Create scope for temporary variable holding dispatch receiver
|
||||
// It is used both during method reference and passing `this` value to `apply` function.
|
||||
JsNameRef(
|
||||
"call",
|
||||
JsFunction(
|
||||
context.currentScope,
|
||||
JsBlock(
|
||||
@@ -297,7 +299,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
)
|
||||
),
|
||||
"VarargIIFE"
|
||||
)
|
||||
)),
|
||||
JsThisRef()
|
||||
)
|
||||
} else {
|
||||
JsInvocation(
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGene
|
||||
val argument = expression.getValueArgument(index)
|
||||
val result = argument?.accept(transformer, context)
|
||||
if (result == null) {
|
||||
assert(expression is IrFunctionAccessExpression && expression.symbol.owner.isEffectivelyExternal())
|
||||
require(expression is IrFunctionAccessExpression && expression.symbol.owner.isEffectivelyExternal())
|
||||
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
|
||||
} else
|
||||
result
|
||||
|
||||
@@ -48,7 +48,7 @@ private val arrayConstructorPhase = makeIrFilePhase(
|
||||
)
|
||||
|
||||
private val expectDeclarationsRemovingPhase = makeIrFilePhase(
|
||||
::ExpectDeclarationsRemoving,
|
||||
::ExpectDeclarationsRemoveLowering,
|
||||
name = "ExpectDeclarationsRemoving",
|
||||
description = "Remove expect declaration from module fragment"
|
||||
)
|
||||
|
||||
+12
-15
@@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.backend.common.lower
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -15,8 +13,6 @@ import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -25,18 +21,19 @@ import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
|
||||
/**
|
||||
* This pass removes all declarations with `isExpect == true`.
|
||||
*/
|
||||
class ExpectDeclarationsRemoving(val context: BackendContext) : FileLoweringPass {
|
||||
// `doRemove` means should expect-declaration be removed from IR
|
||||
class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
override fun visitFile(declaration: IrFile) {
|
||||
// All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`.
|
||||
irFile.declarations.removeAll {
|
||||
declaration.declarations.removeAll {
|
||||
val descriptor = it.descriptor
|
||||
if (descriptor is MemberDescriptor && descriptor.isExpect) {
|
||||
copyDefaultArgumentsFromExpectToActual(it)
|
||||
true
|
||||
doRemove
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -83,10 +80,10 @@ class ExpectDeclarationsRemoving(val context: BackendContext) : FileLoweringPass
|
||||
}
|
||||
|
||||
private fun IrFunction.findActualForExpected(): IrFunction =
|
||||
context.ir.symbols.externalSymbolTable.referenceFunction(descriptor.findActualForExpect()).owner
|
||||
symbolTable.referenceFunction(descriptor.findActualForExpect()).owner
|
||||
|
||||
private fun IrClass.findActualForExpected(): IrClass =
|
||||
context.ir.symbols.externalSymbolTable.referenceClass(descriptor.findActualForExpect()).owner
|
||||
symbolTable.referenceClass(descriptor.findActualForExpect()).owner
|
||||
|
||||
private inline fun <reified T : MemberDescriptor> T.findActualForExpect() = with(ExpectedActualResolver) {
|
||||
val descriptor = this@findActualForExpect
|
||||
@@ -29,7 +29,9 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.createJsK
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.ExpectDeclarationRemover
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
|
||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -83,6 +85,9 @@ fun generateKLib(
|
||||
val moduleFragment = psi2IrContext.generateModuleFragment(files)
|
||||
|
||||
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
||||
|
||||
moduleFragment.acceptVoid(ExpectDeclarationRemover(psi2IrContext.symbolTable, false))
|
||||
|
||||
serializeModuleIntoKlib(
|
||||
moduleName,
|
||||
configuration.metadataVersion,
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// WITH_RUNTIME
|
||||
// MODULE: lib
|
||||
// FILE: common.kt
|
||||
|
||||
expect fun foo(a: String, b: String = "O"): String
|
||||
|
||||
// FILE: platform.kt
|
||||
|
||||
actual fun foo(a: String, b: String) = a + b
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: main.kt
|
||||
|
||||
fun box(): String {
|
||||
return foo("") + foo("K", "")
|
||||
}
|
||||
+5
@@ -16150,6 +16150,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedFunction.kt")
|
||||
public void testInheritedFromExpectedFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedInterface.kt")
|
||||
public void testInheritedFromExpectedInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedInterface.kt");
|
||||
|
||||
+5
@@ -16155,6 +16155,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedFunction.kt")
|
||||
public void testInheritedFromExpectedFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedInterface.kt")
|
||||
public void testInheritedFromExpectedInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedInterface.kt");
|
||||
|
||||
+5
@@ -16155,6 +16155,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedFunction.kt")
|
||||
public void testInheritedFromExpectedFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedInterface.kt")
|
||||
public void testInheritedFromExpectedInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedInterface.kt");
|
||||
|
||||
Generated
+5
@@ -12365,6 +12365,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedFunction.kt")
|
||||
public void testInheritedFromExpectedFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedInterface.kt")
|
||||
public void testInheritedFromExpectedInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedInterface.kt");
|
||||
|
||||
+5
@@ -13520,6 +13520,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedFunction.kt")
|
||||
public void testInheritedFromExpectedFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFromExpectedInterface.kt")
|
||||
public void testInheritedFromExpectedInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/multiplatform/defaultArguments/inheritedFromExpectedInterface.kt");
|
||||
|
||||
@@ -6,5 +6,9 @@ define("lib", [], function() {
|
||||
return this.x + y;
|
||||
};
|
||||
|
||||
A.prototype.bar = function() {
|
||||
return "(" + Array.prototype.join.call(arguments, "") + ")";
|
||||
};
|
||||
|
||||
return A;
|
||||
});
|
||||
@@ -7,12 +7,24 @@ external class A(x: Int = definedExternally) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = definedExternally
|
||||
|
||||
fun bar(vararg arg: String): String = definedExternally
|
||||
}
|
||||
|
||||
class C {
|
||||
val e = arrayOf("e")
|
||||
val f = arrayOf("f")
|
||||
val a = A(1)
|
||||
|
||||
fun qux() = a.bar(*e, *f)
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val a = A(23)
|
||||
assertEquals(23, a.x)
|
||||
assertEquals(65, a.foo(42))
|
||||
assertEquals(C().qux(), "(ef)")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user