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.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
}
@@ -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
}
@@ -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
@@ -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
@@ -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}'"
)
@@ -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) "<Uninitialized>"
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() ?: "<Uninitialized>"
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()
}