Skip to content

Commit

Permalink
IR: fix thisReceiver parameter type for function classes
Browse files Browse the repository at this point in the history
Incorrect builder was used at line 269, which led to non-sensible type
in `IrClass.thisReceiver` for function types, such as
`SuspendFunction1<SuspendFunction1, SuspendFunction1>` in the linked
issue.

Avoid creating types manually completely to simplify this code and fix
the bug.

 #KT-49168 Fixed
  • Loading branch information
udalov committed Nov 10, 2021
1 parent 5b9268a commit 27cfcb9
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 23 deletions.

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 @@ -32,7 +32,10 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.referenceClassifier
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
Expand All @@ -54,7 +57,7 @@ class IrBuiltInsOverDescriptors(
get() =
synchronized(this) {
if (_functionFactory == null) {
_functionFactory = IrDescriptorBasedFunctionFactory(this, symbolTable)
_functionFactory = IrDescriptorBasedFunctionFactory(this, symbolTable, typeTranslator)
}
_functionFactory!!
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ abstract class IrAbstractDescriptorBasedFunctionFactory {
class IrDescriptorBasedFunctionFactory(
private val irBuiltIns: IrBuiltInsOverDescriptors,
private val symbolTable: SymbolTable,
private val typeTranslator: TypeTranslator,
getPackageFragment: ((PackageFragmentDescriptor) -> IrPackageFragment)? = null,
// Needed for JS and Wasm backends to "preload" interfaces that can referenced during lowerings
private val referenceFunctionsWhenKFunctionAreReferenced: Boolean = false,
Expand Down Expand Up @@ -257,29 +258,16 @@ class IrDescriptorBasedFunctionFactory(
}
}

private fun IrClass.createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter {
val vDescriptor = descriptorFactory.classReceiverParameterDescriptor()
val vSymbol = IrValueParameterSymbolImpl(vDescriptor)
val type = with(IrSimpleTypeBuilder()) {
classifier = symbol
arguments = typeParameters.run {
val builder = IrSimpleTypeBuilder()
mapTo(ArrayList(size)) {
builder.classifier = it.symbol
buildTypeProjection()
}
}
buildSimpleType()
}
val vDeclaration = irFactory.createValueParameter(
offset, offset, classOrigin, vSymbol, SpecialNames.THIS, -1, type, null,
private fun createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter {
val descriptor = descriptorFactory.classReceiverParameterDescriptor()
return irFactory.createValueParameter(
offset, offset, classOrigin, IrValueParameterSymbolImpl(descriptor), SpecialNames.THIS, -1,
typeTranslator.translateType(descriptor.type), null,
isCrossinline = false,
isNoinline = false,
isHidden = false,
isAssignable = false
)

return vDeclaration
}

private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, descriptorFactory: FunctionDescriptorFactory) {
Expand Down Expand Up @@ -435,7 +423,7 @@ class IrDescriptorBasedFunctionFactory(

val r = klass.createTypeParameters(n, descriptorFactory)

klass.thisReceiver = klass.createThisReceiver(descriptorFactory).also { it.parent = klass }
klass.thisReceiver = createThisReceiver(descriptorFactory).also { it.parent = klass }

klass.superTypes = listOf(with(IrSimpleTypeBuilder()) {
classifier = baseClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSeria
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
Expand All @@ -56,7 +55,6 @@ import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.progress.IncrementalNextRoundException
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
Expand Down Expand Up @@ -429,6 +427,7 @@ fun getIrModuleInfoForKlib(
irBuiltIns.functionFactory = IrDescriptorBasedFunctionFactory(
irBuiltIns,
symbolTable,
typeTranslator,
if (loadFunctionInterfacesIntoStdlib) getFunctionFactoryCallback(deserializedModuleFragments.first()) else null,
true
)
Expand Down Expand Up @@ -483,6 +482,7 @@ fun getIrModuleInfoForSourceFiles(
IrDescriptorBasedFunctionFactory(
irBuiltIns,
symbolTable,
psi2IrContext.typeTranslator,
if (loadFunctionInterfacesIntoStdlib) getFunctionFactoryCallback(deserializedModuleFragments.first()) else null,
true
)
Expand Down
27 changes: 27 additions & 0 deletions compiler/testData/codegen/box/coroutines/kt49168.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS

import helpers.*
import kotlin.coroutines.*

fun interface Print {
suspend fun print(msg: String): String
}

object Context : Print by Print(::id)

fun id(x: String): String = x

fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}

fun box(): String {
var result = "Fail"
builder {
result = Context.print("OK")
}
return result
}

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.

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.

0 comments on commit 27cfcb9

Please sign in to comment.