Skip to content

Commit

Permalink
JS: support explicit SAM constructor invocation
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-bannykh committed Apr 15, 2020
1 parent 0ee32ea commit 8179828
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 4 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 28 additions & 2 deletions compiler/testData/codegen/box/funInterface/primitiveConversions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,37 @@ fun interface CharToAny {
fun invoke(c: Char): Any
}

fun foo(c: CharToAny): Any = c.invoke('O')
fun interface GenericToAny<T> {
fun invoke(t: T): Any
}

fun interface GenericCharToAny: GenericToAny<Char>

fun foo1(c: CharToAny): Any = c.invoke('1')

fun <T> foo2(t: T, g: GenericToAny<T>): Any = g.invoke(t)

fun foo3(c: GenericCharToAny) = c.invoke('3')

fun box(): String {

if (foo { it } !is Char) return "fail"
val c1 = foo1 { it }
if (c1 !is Char || c1 != '1') return "fail1"

val c2 = foo2<Char>('2') { it }
if (c2 !is Char || c2 != '2') return "fail2"

val c3 = foo3 { it }
if (c3 !is Char || c3 != '3') return "fail3"

val c4 = CharToAny { it }.invoke('4')
if (c4 !is Char || c4 != '4') return "fail4"

val c5 = GenericToAny<Char> { it }.invoke('5')
if (c5 !is Char || c5 != '5') return "fail5"

val c6 = GenericCharToAny { it }.invoke('6')
if (c6 !is Char || c6 != '6') return "fail6"

return "OK"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// !LANGUAGE: +FunctionalInterfaceConversion
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_DCE_DRIVEN

fun interface S {
fun invoke(): String
}

fun interface G<T> {
fun foo(t: T): T
}

fun interface C: G<Char>

fun interface C2 {
fun bar(c: Char): Char
}

fun box(): String {
val g = G<Int> { it * 10 }
if (g.foo(2) != 20) return "fail1"

val g2 = G { a: Char -> a + 1 }
if (g2.foo('a') != 'b') return "fail2"

val c = C { it + 2 }
if (c.foo('A') != 'C') return "fail3"

val c2 = C2 { it + 3 }
if (c2.bar('0') != '3') return "fail4"

return S { "OK" }.invoke()
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*

Expand Down Expand Up @@ -184,7 +185,7 @@ object InvokeIntrinsic : FunctionCallCase() {

object ConstructorCallCase : FunctionCallCase() {
fun canApply(callInfo: FunctionCallInfo): Boolean {
return callInfo.callableDescriptor is ConstructorDescriptor
return callInfo.callableDescriptor is ConstructorDescriptor || callInfo.callableDescriptor is SamConstructorDescriptor
}

override fun FunctionCallInfo.noReceivers() = doTranslate { translateArguments }
Expand All @@ -197,6 +198,11 @@ object ConstructorCallCase : FunctionCallCase() {
getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List<JsExpression>
): JsExpression {
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)

if (callableDescriptor is SamConstructorDescriptor) {
return JsNew(functionRef, argumentsInfo.getArguments())
}

val invocationArguments = mutableListOf<JsExpression>()

val constructorDescriptor = callableDescriptor as ClassConstructorDescriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ class ClassTranslator private constructor(
listOfNotNull(innerContext.continuationParameterDescriptor)

val arguments = parameters.map {
TranslationUtils.coerce(innerContext, innerContext.getAliasForDescriptor(it)!!, context.currentModule.builtIns.anyType)
TranslationUtils.coerce(innerContext, ReferenceTranslator.translateAsValueReference(it, innerContext), context.currentModule.builtIns.anyType)
}

function.body = JsBlock(JsReturn(JsInvocation(pureFqn(Namer.SAM_FIELD_NAME, JsThisRef()), arguments)))
Expand Down

0 comments on commit 8179828

Please sign in to comment.