JVM IR: slightly cleanup and split IrUtils.kt
- Move IrType-specific utilities to separate JvmIrTypeUtils.kt - Extract JvmIrBuilder to a separate file - Rename IrUtils.kt to JvmIrUtils.kt to be able to tell it apart from numerous other IR utils files
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.jvm.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
|
||||||
|
import org.jetbrains.kotlin.ir.builders.Scope
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
|
||||||
|
// An IR builder with a reference to the JvmBackendContext
|
||||||
|
class JvmIrBuilder(
|
||||||
|
val backendContext: JvmBackendContext,
|
||||||
|
val symbol: IrSymbol,
|
||||||
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
endOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
) : IrBuilderWithScope(
|
||||||
|
IrGeneratorContextBase(backendContext.irBuiltIns),
|
||||||
|
Scope(symbol),
|
||||||
|
startOffset,
|
||||||
|
endOffset
|
||||||
|
) {
|
||||||
|
val irSymbols: JvmSymbols
|
||||||
|
get() = backendContext.ir.symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JvmBackendContext.createJvmIrBuilder(
|
||||||
|
symbol: IrSymbol,
|
||||||
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
endOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
): JvmIrBuilder = JvmIrBuilder(this, symbol, startOffset, endOffset)
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.jvm.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.representativeUpperBound
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrScript
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.util.isLocal
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform as much type erasure as is significant for JVM signature generation.
|
||||||
|
* Class types are kept as is, while type parameters are replaced with their
|
||||||
|
* erased upper bounds, keeping the nullability information.
|
||||||
|
*
|
||||||
|
* For example, a type parameter `T?` where `T : Any`, `T : Comparable<T>` is
|
||||||
|
* erased to `Any?`.
|
||||||
|
*
|
||||||
|
* Type arguments to the erased upper bound are replaced by `*`, since
|
||||||
|
* recursive erasure could loop. For example, a type parameter
|
||||||
|
* `T : Comparable<T>` is replaced by `Comparable<*>`.
|
||||||
|
*/
|
||||||
|
fun IrType.eraseTypeParameters(): IrType = when (this) {
|
||||||
|
is IrErrorType -> this
|
||||||
|
is IrSimpleType ->
|
||||||
|
when (val owner = classifier.owner) {
|
||||||
|
is IrScript -> {
|
||||||
|
assert(arguments.isEmpty()) { "Script can't be generic: " + owner.render() }
|
||||||
|
IrSimpleTypeImpl(classifier, hasQuestionMark, emptyList(), annotations)
|
||||||
|
}
|
||||||
|
is IrClass -> IrSimpleTypeImpl(classifier, hasQuestionMark, arguments.map { it.eraseTypeParameters() }, annotations)
|
||||||
|
is IrTypeParameter -> {
|
||||||
|
val upperBound = owner.erasedUpperBound
|
||||||
|
IrSimpleTypeImpl(
|
||||||
|
upperBound.symbol,
|
||||||
|
isNullable(),
|
||||||
|
// Should not affect JVM signature, but may result in an invalid type object
|
||||||
|
List(upperBound.typeParameters.size) { IrStarProjectionImpl },
|
||||||
|
owner.annotations
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
||||||
|
}
|
||||||
|
else -> error("Unknown IrType kind: $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrTypeArgument.eraseTypeParameters(): IrTypeArgument = when (this) {
|
||||||
|
is IrStarProjection -> this
|
||||||
|
is IrTypeProjection -> makeTypeProjection(type.eraseTypeParameters(), variance)
|
||||||
|
else -> error("Unknown IrTypeArgument kind: $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the erased class for this type parameter according to the java erasure rules.
|
||||||
|
*/
|
||||||
|
val IrTypeParameter.erasedUpperBound: IrClass
|
||||||
|
get() {
|
||||||
|
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||||
|
for (type in superTypes) {
|
||||||
|
val irClass = type.classOrNull?.owner ?: continue
|
||||||
|
if (!irClass.isJvmInterface) return irClass
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, choose either the first IrClass supertype or recurse.
|
||||||
|
// In the first case, all supertypes are interface types and the choice was arbitrary.
|
||||||
|
// In the second case, there is only a single supertype.
|
||||||
|
return superTypes.first().erasedUpperBound
|
||||||
|
}
|
||||||
|
|
||||||
|
val IrType.erasedUpperBound: IrClass
|
||||||
|
get() = when (val classifier = classifierOrNull) {
|
||||||
|
is IrClassSymbol -> classifier.owner
|
||||||
|
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
||||||
|
is IrScriptSymbol -> classifier.owner.targetClass!!.owner
|
||||||
|
else -> error(render())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default null/0 value for the type.
|
||||||
|
*
|
||||||
|
* This handles unboxing of non-nullable inline class types to their underlying types and produces
|
||||||
|
* a null/0 default value for the resulting type. When such unboxing takes place it ensures that
|
||||||
|
* the value is not reboxed and reunboxed by the codegen by using the unsafeCoerceIntrinsic.
|
||||||
|
*/
|
||||||
|
fun IrType.defaultValue(startOffset: Int, endOffset: Int, context: JvmBackendContext): IrExpression {
|
||||||
|
val classifier = this.classifierOrNull
|
||||||
|
if (classifier is IrTypeParameterSymbol) {
|
||||||
|
return classifier.owner.representativeUpperBound.defaultValue(startOffset, endOffset, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this !is IrSimpleType || hasQuestionMark || classOrNull?.owner?.isInline != true)
|
||||||
|
return IrConstImpl.defaultValueForType(startOffset, endOffset, this)
|
||||||
|
|
||||||
|
val underlyingType = unboxInlineClass()
|
||||||
|
val defaultValueForUnderlyingType = IrConstImpl.defaultValueForType(startOffset, endOffset, underlyingType)
|
||||||
|
return IrCallImpl.fromSymbolOwner(startOffset, endOffset, this, context.ir.symbols.unsafeCoerceIntrinsic).also {
|
||||||
|
it.putTypeArgument(0, underlyingType) // from
|
||||||
|
it.putTypeArgument(1, this) // to
|
||||||
|
it.putValueArgument(0, defaultValueForUnderlyingType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrType.isInlineClassType(): Boolean =
|
||||||
|
erasedUpperBound.isInline
|
||||||
|
|
||||||
|
val IrType.upperBound: IrType
|
||||||
|
get() = erasedUpperBound.symbol.starProjectedType
|
||||||
|
|
||||||
|
fun IrType.eraseToScope(scopeOwner: IrTypeParametersContainer): IrType =
|
||||||
|
eraseToScope(collectVisibleTypeParameters(scopeOwner))
|
||||||
|
|
||||||
|
fun IrType.eraseToScope(visibleTypeParameters: Set<IrTypeParameter>): IrType {
|
||||||
|
require(this is IrSimpleType) { error("Unexpected IrType kind: ${render()}") }
|
||||||
|
return when (classifier) {
|
||||||
|
is IrClassSymbol -> IrSimpleTypeImpl(
|
||||||
|
classifier, hasQuestionMark, arguments.map { it.eraseToScope(visibleTypeParameters) }, annotations
|
||||||
|
)
|
||||||
|
is IrTypeParameterSymbol -> if (classifier.owner in visibleTypeParameters) this else upperBound
|
||||||
|
else -> error("unknown IrType classifier kind: ${classifier.owner.render()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrTypeArgument.eraseToScope(visibleTypeParameters: Set<IrTypeParameter>): IrTypeArgument = when (this) {
|
||||||
|
is IrStarProjection -> this
|
||||||
|
is IrTypeProjection -> makeTypeProjection(type.eraseToScope(visibleTypeParameters), variance)
|
||||||
|
else -> error("unknown type projection kind: ${render()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun collectVisibleTypeParameters(scopeOwner: IrTypeParametersContainer): Set<IrTypeParameter> =
|
||||||
|
generateSequence(scopeOwner) { current ->
|
||||||
|
val parent = current.parent as? IrTypeParametersContainer
|
||||||
|
parent.takeUnless { parent is IrClass && current is IrClass && !current.isInner && !current.isLocal }
|
||||||
|
}
|
||||||
|
.flatMap { it.typeParameters }
|
||||||
|
.toSet()
|
||||||
+3
-160
@@ -9,11 +9,8 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
|
|||||||
import org.jetbrains.kotlin.backend.jvm.CachedFieldsForObjectInstances
|
import org.jetbrains.kotlin.backend.jvm.CachedFieldsForObjectInstances
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineOnly
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineOnly
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.representativeUpperBound
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||||
import org.jetbrains.kotlin.config.JvmDefaultMode
|
import org.jetbrains.kotlin.config.JvmDefaultMode
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
@@ -24,23 +21,17 @@ import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOT
|
|||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.PsiIrFileEntry
|
import org.jetbrains.kotlin.ir.PsiIrFileEntry
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
|
||||||
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
|
|
||||||
import org.jetbrains.kotlin.ir.builders.Scope
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
|
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
@@ -54,97 +45,6 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform as much type erasure as is significant for JVM signature generation.
|
|
||||||
* Class types are kept as is, while type parameters are replaced with their
|
|
||||||
* erased upper bounds, keeping the nullability information.
|
|
||||||
*
|
|
||||||
* For example, a type parameter `T?` where `T : Any`, `T : Comparable<T>` is
|
|
||||||
* erased to `Any?`.
|
|
||||||
*
|
|
||||||
* Type arguments to the erased upper bound are replaced by `*`, since
|
|
||||||
* recursive erasure could loop. For example, a type parameter
|
|
||||||
* `T : Comparable<T>` is replaced by `Comparable<*>`.
|
|
||||||
*/
|
|
||||||
fun IrType.eraseTypeParameters() = when (this) {
|
|
||||||
is IrErrorType -> this
|
|
||||||
is IrSimpleType ->
|
|
||||||
when (val owner = classifier.owner) {
|
|
||||||
is IrScript -> {
|
|
||||||
assert(arguments.isEmpty()) { "Script can't be generic: " + owner.render() }
|
|
||||||
IrSimpleTypeImpl(classifier, hasQuestionMark, emptyList(), annotations)
|
|
||||||
}
|
|
||||||
is IrClass -> IrSimpleTypeImpl(classifier, hasQuestionMark, arguments.map { it.eraseTypeParameters() }, annotations)
|
|
||||||
is IrTypeParameter -> {
|
|
||||||
val upperBound = owner.erasedUpperBound
|
|
||||||
IrSimpleTypeImpl(
|
|
||||||
upperBound.symbol,
|
|
||||||
isNullable(),
|
|
||||||
List(upperBound.typeParameters.size) { IrStarProjectionImpl }, // Should not affect JVM signature, but may result in an invalid type object
|
|
||||||
owner.annotations
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> error("Unknown IrSimpleType classifier kind: $owner")
|
|
||||||
}
|
|
||||||
else -> error("Unknown IrType kind: $this")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrTypeArgument.eraseTypeParameters(): IrTypeArgument = when (this) {
|
|
||||||
is IrStarProjection -> this
|
|
||||||
is IrTypeProjection -> makeTypeProjection(type.eraseTypeParameters(), variance)
|
|
||||||
else -> error("Unknown IrTypeArgument kind: $this")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the erased class for this type parameter according to the java erasure rules.
|
|
||||||
*/
|
|
||||||
val IrTypeParameter.erasedUpperBound: IrClass
|
|
||||||
get() {
|
|
||||||
// Pick the (necessarily unique) non-interface upper bound if it exists
|
|
||||||
for (type in superTypes) {
|
|
||||||
val irClass = type.classOrNull?.owner ?: continue
|
|
||||||
if (!irClass.isJvmInterface) return irClass
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, choose either the first IrClass supertype or recurse.
|
|
||||||
// In the first case, all supertypes are interface types and the choice was arbitrary.
|
|
||||||
// In the second case, there is only a single supertype.
|
|
||||||
return superTypes.first().erasedUpperBound
|
|
||||||
}
|
|
||||||
|
|
||||||
val IrType.erasedUpperBound: IrClass
|
|
||||||
get() = when (val classifier = classifierOrNull) {
|
|
||||||
is IrClassSymbol -> classifier.owner
|
|
||||||
is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound
|
|
||||||
is IrScriptSymbol -> classifier.owner.targetClass!!.owner
|
|
||||||
else -> error(render())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the default null/0 value for the type.
|
|
||||||
*
|
|
||||||
* This handles unboxing of non-nullable inline class types to their underlying types and produces
|
|
||||||
* a null/0 default value for the resulting type. When such unboxing takes place it ensures that
|
|
||||||
* the value is not reboxed and reunboxed by the codegen by using the unsafeCoerceIntrinsic.
|
|
||||||
*/
|
|
||||||
fun IrType.defaultValue(startOffset: Int, endOffset: Int, context: JvmBackendContext): IrExpression {
|
|
||||||
val classifier = this.classifierOrNull
|
|
||||||
if (classifier is IrTypeParameterSymbol) {
|
|
||||||
return classifier.owner.representativeUpperBound.defaultValue(startOffset, endOffset, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this !is IrSimpleType || hasQuestionMark || classOrNull?.owner?.isInline != true)
|
|
||||||
return IrConstImpl.defaultValueForType(startOffset, endOffset, this)
|
|
||||||
|
|
||||||
val underlyingType = unboxInlineClass()
|
|
||||||
val defaultValueForUnderlyingType = IrConstImpl.defaultValueForType(startOffset, endOffset, underlyingType)
|
|
||||||
return IrCallImpl.fromSymbolOwner(startOffset, endOffset, this, context.ir.symbols.unsafeCoerceIntrinsic).also {
|
|
||||||
it.putTypeArgument(0, underlyingType) // from
|
|
||||||
it.putTypeArgument(1, this) // to
|
|
||||||
it.putValueArgument(0, defaultValueForUnderlyingType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrDeclaration.getJvmNameFromAnnotation(): String? {
|
fun IrDeclaration.getJvmNameFromAnnotation(): String? {
|
||||||
// TODO lower @JvmName?
|
// TODO lower @JvmName?
|
||||||
val const = getAnnotation(DescriptorUtils.JVM_NAME)?.getValueArgument(0) as? IrConst<*> ?: return null
|
val const = getAnnotation(DescriptorUtils.JVM_NAME)?.getValueArgument(0) as? IrConst<*> ?: return null
|
||||||
@@ -190,29 +90,6 @@ fun IrValueParameter.isInlineParameter() =
|
|||||||
// making this return `false` requires using `@Suppress`.
|
// making this return `false` requires using `@Suppress`.
|
||||||
(!type.isNullable() || defaultValue?.expression?.type?.isNullable() == false)
|
(!type.isNullable() || defaultValue?.expression?.type?.isNullable() == false)
|
||||||
|
|
||||||
// An IR builder with a reference to the JvmBackendContext
|
|
||||||
class JvmIrBuilder(
|
|
||||||
val backendContext: JvmBackendContext,
|
|
||||||
val symbol: IrSymbol,
|
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
|
||||||
endOffset: Int = UNDEFINED_OFFSET
|
|
||||||
) : IrBuilderWithScope(
|
|
||||||
IrGeneratorContextBase(backendContext.irBuiltIns),
|
|
||||||
Scope(symbol),
|
|
||||||
startOffset,
|
|
||||||
endOffset
|
|
||||||
) {
|
|
||||||
val irSymbols: JvmSymbols
|
|
||||||
get() = backendContext.ir.symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
fun JvmBackendContext.createJvmIrBuilder(
|
|
||||||
symbol: IrSymbol,
|
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
|
||||||
endOffset: Int = UNDEFINED_OFFSET
|
|
||||||
) = JvmIrBuilder(this, symbol, startOffset, endOffset)
|
|
||||||
|
|
||||||
|
|
||||||
fun IrDeclaration.isInCurrentModule(): Boolean =
|
fun IrDeclaration.isInCurrentModule(): Boolean =
|
||||||
getPackageFragment() is IrFile
|
getPackageFragment() is IrFile
|
||||||
|
|
||||||
@@ -356,34 +233,6 @@ val IrDeclaration.isStaticInlineClassReplacement: Boolean
|
|||||||
get() = origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT
|
get() = origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT
|
||||||
|| origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR
|
|| origin == JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR
|
||||||
|
|
||||||
val IrType.upperBound: IrType
|
|
||||||
get() = erasedUpperBound.symbol.starProjectedType
|
|
||||||
|
|
||||||
fun IrType.eraseToScope(scopeOwner: IrTypeParametersContainer): IrType = eraseToScope(collectVisibleTypeParameters(scopeOwner))
|
|
||||||
|
|
||||||
fun IrType.eraseToScope(visibleTypeParameters: Set<IrTypeParameter>): IrType {
|
|
||||||
require(this is IrSimpleType) { error("Unexpected IrType kind: ${render()}") }
|
|
||||||
return when (classifier) {
|
|
||||||
is IrClassSymbol -> IrSimpleTypeImpl(classifier, hasQuestionMark, arguments.map { it.eraseToScope(visibleTypeParameters) }, annotations)
|
|
||||||
is IrTypeParameterSymbol -> if (classifier.owner in visibleTypeParameters) this else upperBound
|
|
||||||
else -> error("unknown IrType classifier kind: ${classifier.owner.render()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrTypeArgument.eraseToScope(visibleTypeParameters: Set<IrTypeParameter>): IrTypeArgument = when (this) {
|
|
||||||
is IrStarProjection -> this
|
|
||||||
is IrTypeProjection -> makeTypeProjection(type.eraseToScope(visibleTypeParameters), variance)
|
|
||||||
else -> error("unknown type projection kind: ${render()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun collectVisibleTypeParameters(scopeOwner: IrTypeParametersContainer): Set<IrTypeParameter> =
|
|
||||||
generateSequence(scopeOwner) { current ->
|
|
||||||
val parent = current.parent as? IrTypeParametersContainer
|
|
||||||
parent.takeUnless { parent is IrClass && current is IrClass && !current.isInner && !current.isLocal }
|
|
||||||
}
|
|
||||||
.flatMap { it.typeParameters }
|
|
||||||
.toSet()
|
|
||||||
|
|
||||||
// On the IR backend we represent raw types as star projected types with a special synthetic annotation.
|
// On the IR backend we represent raw types as star projected types with a special synthetic annotation.
|
||||||
// See `TypeTranslator.translateTypeAnnotations`.
|
// See `TypeTranslator.translateTypeAnnotations`.
|
||||||
private fun JvmBackendContext.makeRawTypeAnnotation() =
|
private fun JvmBackendContext.makeRawTypeAnnotation() =
|
||||||
@@ -395,18 +244,12 @@ private fun JvmBackendContext.makeRawTypeAnnotation() =
|
|||||||
fun IrClass.rawType(context: JvmBackendContext): IrType =
|
fun IrClass.rawType(context: JvmBackendContext): IrType =
|
||||||
defaultType.addAnnotations(listOf(context.makeRawTypeAnnotation()))
|
defaultType.addAnnotations(listOf(context.makeRawTypeAnnotation()))
|
||||||
|
|
||||||
fun IrType.getSingleAbstractMethod(): IrSimpleFunction? =
|
|
||||||
getClass()?.getSingleAbstractMethod()
|
|
||||||
|
|
||||||
fun IrClass.getSingleAbstractMethod(): IrSimpleFunction? =
|
fun IrClass.getSingleAbstractMethod(): IrSimpleFunction? =
|
||||||
functions.singleOrNull { it.modality == Modality.ABSTRACT }
|
functions.singleOrNull { it.modality == Modality.ABSTRACT }
|
||||||
|
|
||||||
fun IrFile.getKtFile(): KtFile? =
|
fun IrFile.getKtFile(): KtFile? =
|
||||||
(fileEntry as? PsiIrFileEntry)?.psiFile as KtFile?
|
(fileEntry as? PsiIrFileEntry)?.psiFile as KtFile?
|
||||||
|
|
||||||
fun IrType.isInlineClassType(): Boolean =
|
|
||||||
erasedUpperBound.isInline
|
|
||||||
|
|
||||||
inline fun IrElement.hasChild(crossinline block: (IrElement) -> Boolean): Boolean {
|
inline fun IrElement.hasChild(crossinline block: (IrElement) -> Boolean): Boolean {
|
||||||
var result = false
|
var result = false
|
||||||
acceptChildren(object : IrElementVisitorVoid {
|
acceptChildren(object : IrElementVisitorVoid {
|
||||||
+1
-1
@@ -140,7 +140,7 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont
|
|||||||
tmp: IrVariable,
|
tmp: IrVariable,
|
||||||
parent: IrDeclarationParent
|
parent: IrDeclarationParent
|
||||||
): IrSimpleFunction {
|
): IrSimpleFunction {
|
||||||
val superMethod = superType.getSingleAbstractMethod()
|
val superMethod = superType.getClass()?.getSingleAbstractMethod()
|
||||||
?: throw AssertionError("SAM type expected: ${superType.render()}")
|
?: throw AssertionError("SAM type expected: ${superType.render()}")
|
||||||
val effectiveValueParametersCount = superMethod.valueParameters.size +
|
val effectiveValueParametersCount = superMethod.valueParameters.size +
|
||||||
if (superMethod.extensionReceiverParameter == null) 0 else 1
|
if (superMethod.extensionReceiverParameter == null) 0 else 1
|
||||||
|
|||||||
Reference in New Issue
Block a user