[PL] Deep rework of the partial linkage

1. Leaving no unbound symbols in the IR tree, KT-54491:
   - All unbound symbols are bound to synthetic stub declarations
   - Improved detection of the root cause for every partially linked classifier
   - Improved error messages

2. Visibility valiation, KT-54469

3. Always check deserialized symbols:
   If the deserialized symbol mismatches the symbol kind at the call site in the deserializer then generate and reference another symbol with the same signature. In case PL is off, just throw IrSymbolTypeMismatchException.

4. Handle class inheritance violation:
   - Detect illegal inheritance (ex: inheriting from a final class)
   - Detect invalid constructor delegation (ex: delegating to another class than the direct superclass)
   - Simplification: Reduce the number of PartialLinkageCase subclasses
   - Reworked error message generation to have shorter and clearer messages

5. Handle class transformations and all known side-effects, examples:
   - nested <-> inner
   - class <-> enum/object
   - adding/removing subclasses of sealed class
   - adding/removing enum entries

6. Check direct instantiation of abstract class.
   Such instantiation could be possible if a class was non-abstract in the previous version of a library.

7. Handle unlinked annotations on declarations.
   Such annotations are removed from the IR. The appropriate compiler error message is produced for every individual case.

8. Handle value argument count mismatch at call sites

9. Handle calling suspend function from non-suspend context.
   This could happen if a suspen function was non-suspend in the previous version of a library.

10. Handle overriding inline callables.
    Only the leaf final callable can be marked with `inline`.

11. Detect illegal non-local returns from noinline/crossinline lambdas.
This commit is contained in:
Dmitriy Dolovov
2022-10-17 18:57:58 +02:00
committed by Space Team
parent 974ee3139c
commit 2a4d880037
69 changed files with 3526 additions and 1397 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.compilationException
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.linkage.partial.createPartialLinkageSupportForLowerings
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -35,10 +36,7 @@ import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.backend.ast.JsExpressionStatement
import org.jetbrains.kotlin.js.backend.ast.JsFunction
import org.jetbrains.kotlin.js.config.ErrorTolerancePolicy
@@ -409,4 +407,10 @@ class JsIrBackendContext(
outlinedJsCodeFunctions[symbol] = parsedJsFunction
return parsedJsFunction
}
override val partialLinkageSupport = createPartialLinkageSupportForLowerings(
isEnabled = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false,
irBuiltIns,
configuration.irMessageLogger
)
}
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnboundSymbols
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
@@ -5,10 +5,10 @@
package org.jetbrains.kotlin.ir.backend.js.ic
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.checkIsFunctionInterface
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
@@ -6,22 +6,20 @@
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
import org.jetbrains.kotlin.backend.common.lower.coroutines.AbstractAddContinuationToFunctionCallsLowering
import org.jetbrains.kotlin.backend.common.lower.coroutines.AddContinuationToLocalSuspendFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.coroutines.AddContinuationToNonLocalSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
/**
* Requires [AddContinuationToLocalSuspendFunctionsLowering] and
* [AddContinuationToNonLocalSuspendFunctionsLowering] to transform function declarations first.
*/
class AddContinuationToFunctionCallsLowering(override val context: JsCommonBackendContext) : AbstractAddContinuationToFunctionCallsLowering() {
override fun IrSimpleFunction.getContinuationParameter(): IrValueParameter =
if (overriddenSymbols.any {
it.owner.name.asString() == "doResume" && it.owner.parent == context.coroutineSymbols.coroutineImpl.owner
}
) {
dispatchReceiverParameter!!
} else {
valueParameters.last()
}
class AddContinuationToFunctionCallsLowering(
override val context: JsCommonBackendContext
) : AbstractAddContinuationToFunctionCallsLowering() {
override fun IrSimpleFunction.isContinuationItself(): Boolean = overriddenSymbols.any { overriddenSymbol ->
overriddenSymbol.owner.name.asString() == "doResume" && overriddenSymbol.owner.parent == context.coroutineSymbols.coroutineImpl.owner
}
}