From 2573eaa77fb71219e4fe614cc9a3ac20e1a98eca Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 29 Sep 2020 21:34:33 +0200 Subject: [PATCH] IR: do not crash renderer on functions with uninitialized return type This is a follow-up to b497f39c29c0f099dcb0393b712bbabb73c8d15d. It turns out that it didn't help because `IrFunction.returnType` throws exception, and checking for `IrUninitializedType` in `IrType.render` was already too late. Throw and catch specific exception instead. Also add function name into the exception message for better diagnostics elsewhere (can't compute the full FQ name because in cases like KT-42020, the parent is also uninitialized). --- .../ir/declarations/impl/IrConstructorImpl.kt | 3 +- .../ir/declarations/impl/IrFunctionImpl.kt | 5 ++-- .../persistent/PersistentIrConstructor.kt | 3 +- .../persistent/PersistentIrFunction.kt | 5 ++-- .../kotlin/ir/types/impl/IrTypeBase.kt | 6 ++++ .../kotlin/ir/util/RenderIrElement.kt | 28 +++++++++++++------ 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt index badbdeff902..8bb9e678b54 100644 --- a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt +++ b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -54,7 +55,7 @@ class IrConstructorImpl( override var returnType: IrType = returnType get() = if (field === IrUninitializedType) { - error("Return type is not initialized") + throw ReturnTypeIsNotInitializedException(this) } else { field } diff --git a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt index 5deea0813bf..16d5a30ae20 100644 --- a/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt +++ b/compiler/ir/ir.tree.impl/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.ir.declarations.impl +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -44,7 +45,7 @@ abstract class IrFunctionCommonImpl( override var returnType: IrType = returnType get() = if (field === IrUninitializedType) { - error("Return type is not initialized") + throw ReturnTypeIsNotInitializedException(this) } else { field } diff --git a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrConstructor.kt b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrConstructor.kt index e9bd4d68f66..146af147243 100644 --- a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrConstructor.kt +++ b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrConstructor.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -73,7 +74,7 @@ internal class PersistentIrConstructor( override var returnType: IrType get() = returnTypeField.let { - if (it !== IrUninitializedType) it else error("Return type is not initialized") + if (it !== IrUninitializedType) it else throw ReturnTypeIsNotInitializedException(this) } set(c) { returnTypeField = c diff --git a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrFunction.kt b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrFunction.kt index 8308ca56e41..c512b193050 100644 --- a/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrFunction.kt +++ b/compiler/ir/ir.tree.persistent/src/org/jetbrains/kotlin/ir/declarations/persistent/PersistentIrFunction.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.ir.declarations.persistent +import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.persistent.carriers.Carrier @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource @@ -63,7 +64,7 @@ internal abstract class PersistentIrFunctionCommon( final override var returnType: IrType get() = returnTypeField.let { - if (it !== IrUninitializedType) it else error("Return type is not initialized") + if (it !== IrUninitializedType) it else throw ReturnTypeIsNotInitializedException(this) } set(c) { returnTypeField = c diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt index 1f8259e667a..7bbc6f0859d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrTypeBase.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.ir.types.impl +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -63,3 +65,7 @@ object IrUninitializedType : IrType { override fun hashCode(): Int = System.identityHashCode(this) } + +class ReturnTypeIsNotInitializedException(function: IrFunction) : IllegalStateException( + "Return type is not initialized for function '${function.name}'" +) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index f6db31a23f1..a11ecc634f7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.types.Variance @@ -108,8 +108,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl run(fn).trimEnd() private fun IrType.render(): String = - if (this === IrUninitializedType) "" - else "${renderTypeAnnotations(annotations)}${renderTypeInner()}" + "${renderTypeAnnotations(annotations)}${renderTypeInner()}" private fun IrType.renderTypeInner() = when (this) { @@ -252,7 +251,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl if (declaration is IrSimpleFunction) { append(": ") - append(declaration.returnType.render()) + append(declaration.renderReturnType()) } append(' ') @@ -282,8 +281,11 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl append(declaration.name.asString()) - val type = declaration.getter?.returnType ?: declaration.backingField?.type - if (type != null) { + val getter = declaration.getter + if (getter != null) { + append(": ") + append(getter.renderReturnType()) + } else declaration.backingField?.type?.let { type -> append(": ") append(type.render()) } @@ -367,10 +369,20 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl "name:$name visibility:$visibility modality:$modality " + renderTypeParameters() + " " + renderValueParameterTypes() + " " + - "returnType:${returnType.render()} " + + "returnType:${renderReturnType()} " + renderSimpleFunctionFlags() } + private fun IrFunction.renderReturnType(): String = + safeReturnType?.render() ?: "" + + private val IrFunction.safeReturnType: IrType? + get() = try { + returnType + } catch (e: ReturnTypeIsNotInitializedException) { + null + } + private fun renderFlagsList(vararg flags: String?) = flags.filterNotNull().run { if (isNotEmpty()) @@ -407,7 +419,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl "visibility:$visibility " + renderTypeParameters() + " " + renderValueParameterTypes() + " " + - "returnType:${returnType.render()} " + + "returnType:${renderReturnType()} " + renderConstructorFlags() }