[JS IR] Allow restriction of function argument by external type

Add a special annotation @JsExternalTypeArgument for
 marking function parameters. The marked parameter
 accepts an argument with an external type only.

^KT-57479 Fixed
This commit is contained in:
Alexander Korepanov
2023-03-21 15:35:52 +01:00
committed by Space Team
parent 4819593bf4
commit e8be3043cc
21 changed files with 394 additions and 1 deletions
@@ -0,0 +1,143 @@
// FIR_IDENTICAL
@OptIn(ExperimentalStdlibApi::class)
fun anyExample(@JsExternalArgument x : Any) = x
@OptIn(ExperimentalStdlibApi::class)
fun anyOrNullExample(@JsExternalArgument x : Any?) = x
@OptIn(ExperimentalStdlibApi::class)
fun <T> genericExample(@JsExternalArgument x : T) = x
@OptIn(ExperimentalStdlibApi::class)
fun <T> genericOrNullExample(@JsExternalArgument x : T?) = x
@OptIn(ExperimentalStdlibApi::class)
fun dynamicExample(@JsExternalArgument x : dynamic) = x
@OptIn(ExperimentalStdlibApi::class)
fun severalParams(@JsExternalArgument x : Any?, @JsExternalArgument y : Any?, @JsExternalArgument z : dynamic) = x ?: y ?: z
external interface ExternalInterface
fun boxExternalInterface(i: ExternalInterface) {
anyExample(i)
anyOrNullExample(i)
genericExample(i)
genericOrNullExample(i)
dynamicExample(i)
}
fun boxExternalInterfaceOrNull(iOrNull: ExternalInterface?) {
anyOrNullExample(iOrNull)
genericExample(iOrNull)
genericOrNullExample(iOrNull)
dynamicExample(iOrNull)
}
external class ExternalClass
fun boxExternalClass(c: ExternalClass) {
anyExample(c)
anyOrNullExample(c)
genericExample(c)
genericOrNullExample(c)
dynamicExample(c)
}
external object ExternalObject
fun boxExternalObject() {
anyExample(ExternalObject)
anyOrNullExample(ExternalObject)
genericExample(ExternalObject)
genericOrNullExample(ExternalObject)
dynamicExample(ExternalObject)
}
interface Interface
fun boxInterface(i: Interface) {
anyExample(<!JS_EXTERNAL_ARGUMENT!>i<!>)
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>i<!>)
genericExample(<!JS_EXTERNAL_ARGUMENT!>i<!>)
genericOrNullExample(<!JS_EXTERNAL_ARGUMENT!>i<!>)
dynamicExample(<!JS_EXTERNAL_ARGUMENT!>i<!>)
}
fun boxInterfaceOrNull(iOrNull: Interface?) {
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>iOrNull<!>)
genericExample(<!JS_EXTERNAL_ARGUMENT!>iOrNull<!>)
genericOrNullExample(<!JS_EXTERNAL_ARGUMENT!>iOrNull<!>)
dynamicExample(<!JS_EXTERNAL_ARGUMENT!>iOrNull<!>)
}
class Class
fun boxInterface(c: Class) {
anyExample(<!JS_EXTERNAL_ARGUMENT!>c<!>)
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>c<!>)
genericExample(<!JS_EXTERNAL_ARGUMENT!>c<!>)
genericOrNullExample(<!JS_EXTERNAL_ARGUMENT!>c<!>)
dynamicExample(<!JS_EXTERNAL_ARGUMENT!>c<!>)
}
object Object
fun boxObject() {
anyExample(<!JS_EXTERNAL_ARGUMENT!>Object<!>)
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>Object<!>)
genericExample(<!JS_EXTERNAL_ARGUMENT!>Object<!>)
genericOrNullExample(<!JS_EXTERNAL_ARGUMENT!>Object<!>)
dynamicExample(<!JS_EXTERNAL_ARGUMENT!>Object<!>)
}
fun boxDynamic(d: dynamic) {
anyExample(<!JS_EXTERNAL_ARGUMENT!>d<!>)
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>d<!>)
genericExample(<!JS_EXTERNAL_ARGUMENT!>d<!>)
genericOrNullExample(<!JS_EXTERNAL_ARGUMENT!>d<!>)
dynamicExample(<!JS_EXTERNAL_ARGUMENT!>d<!>)
}
fun boxPrimitiveTypes() {
anyExample(<!JS_EXTERNAL_ARGUMENT!>1<!>)
anyExample(<!JS_EXTERNAL_ARGUMENT!>1.2<!>)
anyExample(<!JS_EXTERNAL_ARGUMENT!>true<!>)
anyExample(<!JS_EXTERNAL_ARGUMENT!>"hello"<!>)
anyExample(<!JS_EXTERNAL_ARGUMENT!>{}<!>)
anyExample(<!JS_EXTERNAL_ARGUMENT!>{}()<!>)
anyOrNullExample(<!JS_EXTERNAL_ARGUMENT!>null<!>)
}
fun boxArgExpression(i: Interface, iOrNull: Interface?) {
anyExample(<!JS_EXTERNAL_ARGUMENT!>iOrNull ?: i<!>)
}
fun boxNamedArgExpression(i: Interface, iOrNull: Interface?, d: dynamic) {
anyExample(x = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: i<!>)
severalParams(
x = <!JS_EXTERNAL_ARGUMENT!>i<!>,
y = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: i<!>,
z = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: d<!>
)
severalParams(
z = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: d<!>,
x = <!JS_EXTERNAL_ARGUMENT!>i<!>,
y = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: i<!>
)
severalParams(
<!JS_EXTERNAL_ARGUMENT!>i<!>,
z = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: d<!>,
y = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: i<!>
)
severalParams(
x = <!JS_EXTERNAL_ARGUMENT!>i<!>,
y = ExternalObject,
z = <!JS_EXTERNAL_ARGUMENT!>iOrNull ?: d<!>
)
}
@@ -0,0 +1,61 @@
package
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun anyExample(/*0*/ @kotlin.js.JsExternalArgument x: kotlin.Any): kotlin.Any
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun anyOrNullExample(/*0*/ @kotlin.js.JsExternalArgument x: kotlin.Any?): kotlin.Any?
public fun boxArgExpression(/*0*/ i: Interface, /*1*/ iOrNull: Interface?): kotlin.Unit
public fun boxDynamic(/*0*/ d: dynamic): kotlin.Unit
public fun boxExternalClass(/*0*/ c: ExternalClass): kotlin.Unit
public fun boxExternalInterface(/*0*/ i: ExternalInterface): kotlin.Unit
public fun boxExternalInterfaceOrNull(/*0*/ iOrNull: ExternalInterface?): kotlin.Unit
public fun boxExternalObject(): kotlin.Unit
public fun boxInterface(/*0*/ c: Class): kotlin.Unit
public fun boxInterface(/*0*/ i: Interface): kotlin.Unit
public fun boxInterfaceOrNull(/*0*/ iOrNull: Interface?): kotlin.Unit
public fun boxNamedArgExpression(/*0*/ i: Interface, /*1*/ iOrNull: Interface?, /*2*/ d: dynamic): kotlin.Unit
public fun boxObject(): kotlin.Unit
public fun boxPrimitiveTypes(): kotlin.Unit
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun dynamicExample(/*0*/ @kotlin.js.JsExternalArgument x: dynamic): dynamic
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun </*0*/ T> genericExample(/*0*/ @kotlin.js.JsExternalArgument x: T): T
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun </*0*/ T> genericOrNullExample(/*0*/ @kotlin.js.JsExternalArgument x: T?): T?
@kotlin.OptIn(markerClass = {kotlin.ExperimentalStdlibApi::class}) public fun severalParams(/*0*/ @kotlin.js.JsExternalArgument x: kotlin.Any?, /*1*/ @kotlin.js.JsExternalArgument y: kotlin.Any?, /*2*/ @kotlin.js.JsExternalArgument z: dynamic): dynamic
public final class Class {
public constructor Class()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final external class ExternalClass {
public constructor ExternalClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public external interface ExternalInterface {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public external object ExternalObject {
private constructor ExternalObject()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Interface {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Object {
private constructor Object()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}