IR: do not crash renderer on functions with uninitialized return type

This is a follow-up to b497f39c29. 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).
This commit is contained in:
Alexander Udalov
2020-09-29 21:34:33 +02:00
parent 06f1bd6101
commit 2573eaa77f
6 changed files with 36 additions and 14 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType 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.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -54,7 +55,7 @@ class IrConstructorImpl(
override var returnType: IrType = returnType override var returnType: IrType = returnType
get() = if (field === IrUninitializedType) { get() = if (field === IrUninitializedType) {
error("Return type is not initialized") throw ReturnTypeIsNotInitializedException(this)
} else { } else {
field field
} }
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.declarations.impl package org.jetbrains.kotlin.ir.declarations.impl
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor 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.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType 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.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -44,7 +45,7 @@ abstract class IrFunctionCommonImpl(
override var returnType: IrType = returnType override var returnType: IrType = returnType
get() = if (field === IrUninitializedType) { get() = if (field === IrUninitializedType) {
error("Return type is not initialized") throw ReturnTypeIsNotInitializedException(this)
} else { } else {
field field
} }
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType 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.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -73,7 +74,7 @@ internal class PersistentIrConstructor(
override var returnType: IrType override var returnType: IrType
get() = returnTypeField.let { get() = returnTypeField.let {
if (it !== IrUninitializedType) it else error("Return type is not initialized") if (it !== IrUninitializedType) it else throw ReturnTypeIsNotInitializedException(this)
} }
set(c) { set(c) {
returnTypeField = c returnTypeField = c
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.declarations.persistent package org.jetbrains.kotlin.ir.declarations.persistent
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.persistent.carriers.Carrier 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.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType 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.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -63,7 +64,7 @@ internal abstract class PersistentIrFunctionCommon(
final override var returnType: IrType final override var returnType: IrType
get() = returnTypeField.let { get() = returnTypeField.let {
if (it !== IrUninitializedType) it else error("Return type is not initialized") if (it !== IrUninitializedType) it else throw ReturnTypeIsNotInitializedException(this)
} }
set(c) { set(c) {
returnTypeField = c returnTypeField = c
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.ir.types.impl 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.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -63,3 +65,7 @@ object IrUninitializedType : IrType {
override fun hashCode(): Int = System.identityHashCode(this) override fun hashCode(): Int = System.identityHashCode(this)
} }
class ReturnTypeIsNotInitializedException(function: IrFunction) : IllegalStateException(
"Return type is not initialized for function '${function.name}'"
)
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol 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.IrUninitializedType import org.jetbrains.kotlin.ir.types.impl.ReturnTypeIsNotInitializedException
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -108,8 +108,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
run(fn).trimEnd() run(fn).trimEnd()
private fun IrType.render(): String = private fun IrType.render(): String =
if (this === IrUninitializedType) "<Uninitialized>" "${renderTypeAnnotations(annotations)}${renderTypeInner()}"
else "${renderTypeAnnotations(annotations)}${renderTypeInner()}"
private fun IrType.renderTypeInner() = private fun IrType.renderTypeInner() =
when (this) { when (this) {
@@ -252,7 +251,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
if (declaration is IrSimpleFunction) { if (declaration is IrSimpleFunction) {
append(": ") append(": ")
append(declaration.returnType.render()) append(declaration.renderReturnType())
} }
append(' ') append(' ')
@@ -282,8 +281,11 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
append(declaration.name.asString()) append(declaration.name.asString())
val type = declaration.getter?.returnType ?: declaration.backingField?.type val getter = declaration.getter
if (type != null) { if (getter != null) {
append(": ")
append(getter.renderReturnType())
} else declaration.backingField?.type?.let { type ->
append(": ") append(": ")
append(type.render()) append(type.render())
} }
@@ -367,10 +369,20 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
"name:$name visibility:$visibility modality:$modality " + "name:$name visibility:$visibility modality:$modality " +
renderTypeParameters() + " " + renderTypeParameters() + " " +
renderValueParameterTypes() + " " + renderValueParameterTypes() + " " +
"returnType:${returnType.render()} " + "returnType:${renderReturnType()} " +
renderSimpleFunctionFlags() renderSimpleFunctionFlags()
} }
private fun IrFunction.renderReturnType(): String =
safeReturnType?.render() ?: "<Uninitialized>"
private val IrFunction.safeReturnType: IrType?
get() = try {
returnType
} catch (e: ReturnTypeIsNotInitializedException) {
null
}
private fun renderFlagsList(vararg flags: String?) = private fun renderFlagsList(vararg flags: String?) =
flags.filterNotNull().run { flags.filterNotNull().run {
if (isNotEmpty()) if (isNotEmpty())
@@ -407,7 +419,7 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
"visibility:$visibility " + "visibility:$visibility " +
renderTypeParameters() + " " + renderTypeParameters() + " " +
renderValueParameterTypes() + " " + renderValueParameterTypes() + " " +
"returnType:${returnType.render()} " + "returnType:${renderReturnType()} " +
renderConstructorFlags() renderConstructorFlags()
} }