[K/N][IR] Fix for https://youtrack.jetbrains.com/issue/KT-47814
This commit is contained in:
+23
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMo
|
|||||||
import org.jetbrains.kotlin.backend.konan.MemoryModel
|
import org.jetbrains.kotlin.backend.konan.MemoryModel
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||||
|
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer
|
import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
||||||
@@ -149,6 +150,26 @@ internal val copyDefaultValuesToActualPhase = konanUnitPhase(
|
|||||||
description = "Copy default values from expect to actual declarations"
|
description = "Copy default values from expect to actual declarations"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sometimes psi2ir produces IR with non-trivial variance in super types of SAM conversions (this is a language design issue).
|
||||||
|
* Earlier this was solved with just erasing all such variances but this might lead to some other hard to debug problems,
|
||||||
|
* so after handling the majority of corner cases correctly in psi2ir it is safe to assume that such cases don't get here and
|
||||||
|
* even if they do, then it's better to throw an error right away than to dig out weird crashes down the pipeline or even at runtime.
|
||||||
|
* We explicitly check this, also fixing older klibs built with previous compiler versions by applying the same trick as before.
|
||||||
|
*/
|
||||||
|
internal val checkSamSuperTypesPhase = konanUnitPhase(
|
||||||
|
op = {
|
||||||
|
irModule!!.files
|
||||||
|
.forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.THROW).run() }
|
||||||
|
// TODO: This is temporary for handling klibs produced with earlier compiler versions.
|
||||||
|
irModules.values
|
||||||
|
.flatMap { it.files }
|
||||||
|
.forEach { SamSuperTypesChecker(this, it, mode = SamSuperTypesChecker.Mode.ERASE).run() }
|
||||||
|
},
|
||||||
|
name = "CheckSamSuperTypes",
|
||||||
|
description = "Check SAM conversions super types"
|
||||||
|
)
|
||||||
|
|
||||||
internal val serializerPhase = konanUnitPhase(
|
internal val serializerPhase = konanUnitPhase(
|
||||||
op = {
|
op = {
|
||||||
val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) ?: false
|
val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) ?: false
|
||||||
@@ -424,6 +445,7 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
|
|||||||
psiToIrPhase then
|
psiToIrPhase then
|
||||||
destroySymbolTablePhase then
|
destroySymbolTablePhase then
|
||||||
copyDefaultValuesToActualPhase then
|
copyDefaultValuesToActualPhase then
|
||||||
|
checkSamSuperTypesPhase then
|
||||||
serializerPhase then
|
serializerPhase then
|
||||||
specialBackendChecksPhase then
|
specialBackendChecksPhase then
|
||||||
namedUnitPhase(
|
namedUnitPhase(
|
||||||
@@ -484,5 +506,6 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
|||||||
disableIf(destroySymbolTablePhase, isDescriptorsOnlyLibrary)
|
disableIf(destroySymbolTablePhase, isDescriptorsOnlyLibrary)
|
||||||
disableIf(copyDefaultValuesToActualPhase, isDescriptorsOnlyLibrary)
|
disableIf(copyDefaultValuesToActualPhase, isDescriptorsOnlyLibrary)
|
||||||
disableIf(specialBackendChecksPhase, isDescriptorsOnlyLibrary)
|
disableIf(specialBackendChecksPhase, isDescriptorsOnlyLibrary)
|
||||||
|
disableIf(checkSamSuperTypesPhase, isDescriptorsOnlyLibrary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.konan.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
|
internal class SamSuperTypesChecker(private val context: Context,
|
||||||
|
private val irFile: IrFile,
|
||||||
|
private val mode: Mode) {
|
||||||
|
enum class Mode {
|
||||||
|
ERASE,
|
||||||
|
THROW
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrType.eraseProjections(owner: IrElement): IrType {
|
||||||
|
if (this !is IrSimpleType) return this
|
||||||
|
return buildSimpleType {
|
||||||
|
this.classifier = this@eraseProjections.classifier
|
||||||
|
this.hasQuestionMark = this@eraseProjections.hasQuestionMark
|
||||||
|
this.annotations = this@eraseProjections.annotations
|
||||||
|
this.arguments = this@eraseProjections.arguments.mapIndexed { index, argument ->
|
||||||
|
if (argument !is IrTypeProjection)
|
||||||
|
argument
|
||||||
|
else {
|
||||||
|
if (mode == Mode.THROW && argument.variance != Variance.INVARIANT) {
|
||||||
|
context.reportCompilationError(
|
||||||
|
"Unexpected variance in super type argument: ${argument.variance} @$index", irFile, owner)
|
||||||
|
}
|
||||||
|
makeTypeProjection(argument.type.eraseProjections(owner), Variance.INVARIANT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun run() {
|
||||||
|
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
if (expression.operator == IrTypeOperator.SAM_CONVERSION)
|
||||||
|
expression.typeOperand = expression.typeOperand.eraseProjections(expression)
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user