[Wasm] Port JS interop type checker to K2 (KT-56849)
This commit is contained in:
committed by
Space Team
parent
0c46cfd761
commit
15d3bf5e25
+4
@@ -23,5 +23,9 @@ object WASM_DIAGNOSTICS_LIST : DiagnosticList("FirWasmErrors") {
|
|||||||
parameter<ConeKotlinType>("superType")
|
parameter<ConeKotlinType>("superType")
|
||||||
}
|
}
|
||||||
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error<PsiElement>()
|
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error<PsiElement>()
|
||||||
|
val WRONG_JS_INTEROP_TYPE by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||||
|
parameter<String>("place")
|
||||||
|
parameter<ConeKotlinType>("type")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -23,6 +23,7 @@ object FirWasmErrors {
|
|||||||
val NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
val NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||||
val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
val EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||||
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error0<PsiElement>()
|
val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error0<PsiElement>()
|
||||||
|
val WRONG_JS_INTEROP_TYPE by error2<KtElement, String, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
RootDiagnosticRendererFactory.registerFactory(FirWasmErrorsDefaultMessages)
|
RootDiagnosticRendererFactory.registerFactory(FirWasmErrorsDefaultMessages)
|
||||||
|
|||||||
+18
-2
@@ -6,17 +6,33 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.diagnostics.wasm
|
package org.jetbrains.kotlin.fir.analysis.diagnostics.wasm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||||
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers
|
||||||
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderers.TO_STRING
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WRONG_JS_INTEROP_TYPE
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object FirWasmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
object FirWasmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||||
override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { map ->
|
override val MAP = KtDiagnosticFactoryToRendererMap("FIR").also { map ->
|
||||||
map.put(NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE, "Non-external type extends external type {0}", FirDiagnosticRenderers.RENDER_TYPE)
|
map.put(
|
||||||
map.put(EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, "External type extends non-external type {0}", FirDiagnosticRenderers.RENDER_TYPE)
|
NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE,
|
||||||
|
"Non-external type extends external type ''{0}''",
|
||||||
|
FirDiagnosticRenderers.RENDER_TYPE
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE,
|
||||||
|
"External type extends non-external type ''{0}''",
|
||||||
|
FirDiagnosticRenderers.RENDER_TYPE
|
||||||
|
)
|
||||||
map.put(CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION, "This property can only be used from external declarations.")
|
map.put(CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION, "This property can only be used from external declarations.")
|
||||||
|
map.put(
|
||||||
|
WRONG_JS_INTEROP_TYPE,
|
||||||
|
"Type ''{0}'' cannot be used in {1}. Only external, primitive, string and function types are supported in Kotlin/Wasm JS interop.",
|
||||||
|
TO_STRING, FirDiagnosticRenderers.RENDER_TYPE,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.fir.analysis.wasm.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||||
|
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.name.WasmStandardClassIds
|
||||||
|
|
||||||
|
fun FirSimpleFunction.hasValidJsCodeBody(): Boolean =
|
||||||
|
body?.isValidJsCodeBody() == true
|
||||||
|
|
||||||
|
fun FirProperty.hasValidJsCodeBody(): Boolean =
|
||||||
|
this.initializer?.isJsCodeCall() == true
|
||||||
|
|
||||||
|
private fun FirBlock.isValidJsCodeBody(): Boolean {
|
||||||
|
val singleStatement = statements.singleOrNull()
|
||||||
|
?: return false
|
||||||
|
|
||||||
|
return when {
|
||||||
|
singleStatement is FirFunctionCall ->
|
||||||
|
singleStatement.isJsCodeCall()
|
||||||
|
|
||||||
|
singleStatement is FirReturnExpression && this is FirSingleExpressionBlock ->
|
||||||
|
singleStatement.result.isJsCodeCall()
|
||||||
|
|
||||||
|
else ->
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirExpression.isJsCodeCall(): Boolean {
|
||||||
|
if (this !is FirFunctionCall)
|
||||||
|
return false
|
||||||
|
|
||||||
|
val symbol = calleeReference.toResolvedCallableSymbol()
|
||||||
|
?: return false
|
||||||
|
|
||||||
|
return symbol.callableId == WasmStandardClassIds.Callables.Js
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.fir.analysis.wasm.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
|
import org.jetbrains.kotlin.name.WasmStandardClassIds
|
||||||
|
|
||||||
|
fun isJsExportedDeclaration(declaration: FirDeclaration, session: FirSession): Boolean {
|
||||||
|
if (declaration !is FirSimpleFunction)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (declaration.visibility != Visibilities.Public)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (declaration.hasAnnotation(WasmStandardClassIds.Annotations.JsExport, session))
|
||||||
|
return true
|
||||||
|
|
||||||
|
val containerFile = session.firProvider.getFirCallableContainerFile(declaration.symbol)
|
||||||
|
return containerFile != null && containerFile.hasAnnotation(WasmStandardClassIds.Annotations.JsExport, session)
|
||||||
|
}
|
||||||
+5
@@ -13,4 +13,9 @@ object WasmDeclarationCheckers : DeclarationCheckers() {
|
|||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirWasmExternalInheritanceChecker,
|
FirWasmExternalInheritanceChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirWasmJsInteropTypesChecker,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+158
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.fir.analysis.wasm.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.hasValidJsCodeBody
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.isJsExportedDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.name.WasmStandardClassIds
|
||||||
|
|
||||||
|
object FirWasmJsInteropTypesChecker : FirBasicDeclarationChecker() {
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val session = context.session
|
||||||
|
|
||||||
|
fun isExternalJsInteropDeclaration() =
|
||||||
|
declaration.symbol.isEffectivelyExternal(session) &&
|
||||||
|
!declaration.annotations.hasAnnotation(WasmStandardClassIds.Annotations.WasmImport, session)
|
||||||
|
|
||||||
|
fun isJsCodeDeclaration() =
|
||||||
|
(declaration is FirSimpleFunction && declaration.hasValidJsCodeBody()) ||
|
||||||
|
(declaration is FirProperty && declaration.hasValidJsCodeBody())
|
||||||
|
|
||||||
|
fun isJsExportDeclaration() =
|
||||||
|
declaration is FirSimpleFunction && isJsExportedDeclaration(declaration, session)
|
||||||
|
|
||||||
|
// Interop type restriction rules apply uniformly to external, js("code"), and @JsExport declarations
|
||||||
|
if (
|
||||||
|
!isExternalJsInteropDeclaration() &&
|
||||||
|
!isJsCodeDeclaration() &&
|
||||||
|
!isJsExportDeclaration()
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip enums to avoid reporting errors for synthetic static members with unsupported interop types.
|
||||||
|
// External enums errors are reported in a separate checker.
|
||||||
|
if (context.containingDeclarations.any { it is FirClass && it.isEnumClass }) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ConeKotlinType.checkJsInteropType(
|
||||||
|
typePositionDescription: String,
|
||||||
|
source: KtSourceElement?,
|
||||||
|
isInFunctionReturnPosition: Boolean = false,
|
||||||
|
) {
|
||||||
|
if (!isTypeSupportedInJsInterop(this, isInFunctionReturnPosition, session)) {
|
||||||
|
reporter.reportOn(
|
||||||
|
source,
|
||||||
|
FirWasmErrors.WRONG_JS_INTEROP_TYPE,
|
||||||
|
typePositionDescription,
|
||||||
|
this,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirTypeParameterRef.checkJsInteropTypeParameter() {
|
||||||
|
for (upperBound in this.symbol.resolvedBounds) {
|
||||||
|
upperBound.type.checkJsInteropType(
|
||||||
|
"JS interop type parameter upper bound",
|
||||||
|
upperBound.source ?: this.source
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration is FirMemberDeclaration) {
|
||||||
|
for (typeParameter in declaration.typeParameters) {
|
||||||
|
typeParameter.checkJsInteropTypeParameter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (declaration) {
|
||||||
|
is FirProperty -> {
|
||||||
|
declaration.returnTypeRef.coneType.checkJsInteropType(
|
||||||
|
"JS interop property",
|
||||||
|
declaration.source
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is FirFunction -> {
|
||||||
|
for (parameter in declaration.valueParameters) {
|
||||||
|
val type = parameter.returnTypeRef.coneType
|
||||||
|
val varargElementTypeOrType = if (parameter.isVararg) type.varargElementType() else type
|
||||||
|
varargElementTypeOrType.checkJsInteropType(
|
||||||
|
"JS interop function parameter",
|
||||||
|
parameter.source
|
||||||
|
)
|
||||||
|
}
|
||||||
|
declaration.returnTypeRef.coneType.checkJsInteropType(
|
||||||
|
"JS interop function return",
|
||||||
|
declaration.source,
|
||||||
|
isInFunctionReturnPosition = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTypeSupportedInJsInterop(
|
||||||
|
unexpandedType: ConeKotlinType,
|
||||||
|
isInFunctionReturnPosition: Boolean,
|
||||||
|
session: FirSession,
|
||||||
|
): Boolean {
|
||||||
|
val type = unexpandedType.fullyExpandedType(session)
|
||||||
|
|
||||||
|
if (type.isUnit || type.isNothing) {
|
||||||
|
return isInFunctionReturnPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
val nonNullable = type.withNullability(ConeNullability.NOT_NULL, session.typeContext)
|
||||||
|
|
||||||
|
if (nonNullable.isPrimitive || nonNullable.isString) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop type parameters upper bounds should be checked
|
||||||
|
// on declaration site separately
|
||||||
|
if (nonNullable is ConeTypeParameterType) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val regularClassSymbol = nonNullable.toRegularClassSymbol(session)
|
||||||
|
if (regularClassSymbol?.isEffectivelyExternal(session) == true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isBasicFunctionType(session)) {
|
||||||
|
val arguments = type.typeArguments
|
||||||
|
for (i in 0 until arguments.lastIndex) {
|
||||||
|
val argType = arguments[i].type ?: return false
|
||||||
|
if (!isTypeSupportedInJsInterop(argType, isInFunctionReturnPosition = false, session)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnType = arguments.last().type ?: return false
|
||||||
|
return isTypeSupportedInJsInterop(
|
||||||
|
returnType,
|
||||||
|
isInFunctionReturnPosition = true,
|
||||||
|
session
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ fun funBlockBody(x: Int): Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>returnTypeNotSepcified<!>() = js("1")
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>returnTypeNotSepcified<!>() = js("1")
|
||||||
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>valTypeNotSepcified<!> = js("1")
|
<!WRONG_JS_INTEROP_TYPE!>val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>valTypeNotSepcified<!><!> = js("1")
|
||||||
|
|
||||||
val a = "1"
|
val a = "1"
|
||||||
fun nonConst(): String = "1"
|
fun nonConst(): String = "1"
|
||||||
|
|||||||
+27
-22
@@ -67,45 +67,50 @@ external fun <
|
|||||||
T3 : T1?
|
T3 : T1?
|
||||||
> supportedTypeParamtersUpperBounds(p1: T1, p2: T2): T3
|
> supportedTypeParamtersUpperBounds(p1: T1, p2: T2): T3
|
||||||
|
|
||||||
|
external fun supportedVararg(vararg p: Int)
|
||||||
|
|
||||||
external fun wrongExternalTypes(
|
external fun wrongExternalTypes(
|
||||||
any: Any,
|
<!WRONG_JS_INTEROP_TYPE!>any: Any<!>,
|
||||||
nany: Any?,
|
<!WRONG_JS_INTEROP_TYPE!>nany: Any?<!>,
|
||||||
unit: Unit,
|
<!WRONG_JS_INTEROP_TYPE!>unit: Unit<!>,
|
||||||
nunit: Unit?,
|
<!WRONG_JS_INTEROP_TYPE!>nunit: Unit?<!>,
|
||||||
nothing: Nothing,
|
<!WRONG_JS_INTEROP_TYPE!>nothing: Nothing<!>,
|
||||||
nnothing: Nothing?,
|
<!WRONG_JS_INTEROP_TYPE!>nnothing: Nothing?<!>,
|
||||||
charSequence: CharSequence,
|
<!WRONG_JS_INTEROP_TYPE!>charSequence: CharSequence<!>,
|
||||||
list: List<Int>,
|
<!WRONG_JS_INTEROP_TYPE!>list: List<Int><!>,
|
||||||
array: Array<Int>,
|
<!WRONG_JS_INTEROP_TYPE!>array: Array<Int><!>,
|
||||||
intArray: IntArray,
|
<!WRONG_JS_INTEROP_TYPE!>intArray: IntArray<!>,
|
||||||
pair: Pair<Int, Int>,
|
<!WRONG_JS_INTEROP_TYPE!>pair: Pair<Int, Int><!>,
|
||||||
number: Number,
|
<!WRONG_JS_INTEROP_TYPE!>number: Number<!>,
|
||||||
)
|
)
|
||||||
|
|
||||||
external fun <T> supportedTypeParamtersUpperBounds(p: T): T where T : EI, T : Any
|
external fun wrongVararg(<!WRONG_JS_INTEROP_TYPE!>vararg p: Any<!>)
|
||||||
|
|
||||||
|
external fun <T> supportedTypeParamtersUpperBounds(p: T): T where T : EI, T : <!WRONG_JS_INTEROP_TYPE!>Any<!>
|
||||||
|
|
||||||
external fun <
|
external fun <
|
||||||
T1,
|
<!WRONG_JS_INTEROP_TYPE!>T1<!>,
|
||||||
T2 : Number,
|
T2 : <!WRONG_JS_INTEROP_TYPE!>Number<!>,
|
||||||
T3: List<Int>,
|
T3: <!WRONG_JS_INTEROP_TYPE!>List<Int><!>,
|
||||||
> supportedTypeParamtersUpperBounds(
|
> supportedTypeParamtersUpperBounds(
|
||||||
p1: T1,
|
p1: T1,
|
||||||
p2: T2
|
p2: T2
|
||||||
): T3
|
): T3
|
||||||
|
|
||||||
fun jsCode1(x: Any): Any = js("x")
|
<!WRONG_JS_INTEROP_TYPE!>fun jsCode1(<!WRONG_JS_INTEROP_TYPE!>x: Any<!>): Any<!> = js("x")
|
||||||
fun jsCode2(x: Any): Any {
|
<!WRONG_JS_INTEROP_TYPE!>fun jsCode2(<!WRONG_JS_INTEROP_TYPE!>x: Any<!>): Any<!> {
|
||||||
js("return x;")
|
js("return x;")
|
||||||
}
|
}
|
||||||
val jsProp: Any = js("1")
|
<!WRONG_JS_INTEROP_TYPE!>val jsProp: Any<!> = js("1")
|
||||||
|
|
||||||
@JsExport
|
<!WRONG_JS_INTEROP_TYPE!>@JsExport
|
||||||
fun exported(x: Any): Any = x
|
fun exported(<!WRONG_JS_INTEROP_TYPE!>x: Any<!>): Any<!> = x
|
||||||
|
|
||||||
typealias EI_alias = EI
|
typealias EI_alias = EI
|
||||||
typealias Any_alias = Any
|
typealias Any_alias = Any
|
||||||
|
typealias Function_alias = (Int) -> Int
|
||||||
external fun fooAlias(
|
external fun fooAlias(
|
||||||
ei: EI_alias,
|
ei: EI_alias,
|
||||||
any: Any_alias,
|
<!WRONG_JS_INTEROP_TYPE!>any: Any_alias<!>,
|
||||||
|
function: Function_alias,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ external fun <
|
|||||||
T3 : T1?
|
T3 : T1?
|
||||||
> supportedTypeParamtersUpperBounds(p1: T1, p2: T2): T3
|
> supportedTypeParamtersUpperBounds(p1: T1, p2: T2): T3
|
||||||
|
|
||||||
|
external fun supportedVararg(vararg p: Int)
|
||||||
|
|
||||||
external fun wrongExternalTypes(
|
external fun wrongExternalTypes(
|
||||||
<!WRONG_JS_INTEROP_TYPE!>any: Any<!>,
|
<!WRONG_JS_INTEROP_TYPE!>any: Any<!>,
|
||||||
@@ -83,6 +84,8 @@ external fun wrongExternalTypes(
|
|||||||
<!WRONG_JS_INTEROP_TYPE!>number: Number<!>,
|
<!WRONG_JS_INTEROP_TYPE!>number: Number<!>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
external fun wrongVararg(<!WRONG_JS_INTEROP_TYPE!>vararg p: Any<!>)
|
||||||
|
|
||||||
external fun <<!WRONG_JS_INTEROP_TYPE!>T<!>> supportedTypeParamtersUpperBounds(p: T): T where T : EI, T : Any
|
external fun <<!WRONG_JS_INTEROP_TYPE!>T<!>> supportedTypeParamtersUpperBounds(p: T): T where T : EI, T : Any
|
||||||
|
|
||||||
external fun <
|
external fun <
|
||||||
@@ -105,7 +108,9 @@ fun exported(<!WRONG_JS_INTEROP_TYPE!>x: Any<!>): Any<!> = x
|
|||||||
|
|
||||||
typealias EI_alias = EI
|
typealias EI_alias = EI
|
||||||
typealias Any_alias = Any
|
typealias Any_alias = Any
|
||||||
|
typealias Function_alias = (Int) -> Int
|
||||||
external fun fooAlias(
|
external fun fooAlias(
|
||||||
ei: EI_alias,
|
ei: EI_alias,
|
||||||
<!WRONG_JS_INTEROP_TYPE!>any: Any_alias<!>,
|
<!WRONG_JS_INTEROP_TYPE!>any: Any_alias<!>,
|
||||||
|
function: Function_alias,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.name.StandardClassIds.BASE_KOTLIN_PACKAGE
|
|||||||
|
|
||||||
object WasmStandardClassIds {
|
object WasmStandardClassIds {
|
||||||
val BASE_JS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("js"))
|
val BASE_JS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("js"))
|
||||||
|
val BASE_WASM_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("wasm"))
|
||||||
|
|
||||||
object Annotations {
|
object Annotations {
|
||||||
@JvmField
|
@JvmField
|
||||||
@@ -22,14 +23,22 @@ object WasmStandardClassIds {
|
|||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val JsExport = "JsExport".jsId()
|
val JsExport = "JsExport".jsId()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val WasmImport = "WasmImport".wasmId()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Callables {
|
object Callables {
|
||||||
@JvmField
|
@JvmField
|
||||||
val JsDefinedExternally = "definedExternally".callableId(BASE_JS_PACKAGE)
|
val JsDefinedExternally = "definedExternally".callableId(BASE_JS_PACKAGE)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val Js = "js".callableId(BASE_JS_PACKAGE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.jsId() = ClassId(WasmStandardClassIds.BASE_JS_PACKAGE, Name.identifier(this))
|
private fun String.jsId() = ClassId(WasmStandardClassIds.BASE_JS_PACKAGE, Name.identifier(this))
|
||||||
|
|
||||||
|
private fun String.wasmId() = ClassId(WasmStandardClassIds.BASE_WASM_PACKAGE, Name.identifier(this))
|
||||||
|
|
||||||
private fun String.callableId(packageName: FqName) = CallableId(packageName, Name.identifier(this))
|
private fun String.callableId(packageName: FqName) = CallableId(packageName, Name.identifier(this))
|
||||||
|
|||||||
+1
-2
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.wasm.util.hasValidJsCodeBody
|
import org.jetbrains.kotlin.wasm.util.hasValidJsCodeBody
|
||||||
|
|
||||||
// TODO: Implement in K2: KT-56849
|
|
||||||
object WasmJsInteropTypesChecker : DeclarationChecker {
|
object WasmJsInteropTypesChecker : DeclarationChecker {
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||||
if (descriptor !is MemberDescriptor)
|
if (descriptor !is MemberDescriptor)
|
||||||
@@ -119,7 +118,7 @@ private fun isTypeSupportedInJsInterop(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interop type parameters upper bounds should are checked
|
// Interop type parameters upper bounds should be checked
|
||||||
// on declaration site separately
|
// on declaration site separately
|
||||||
if (nonNullable.isTypeParameter()) {
|
if (nonNullable.isTypeParameter()) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
Reference in New Issue
Block a user