IR: optimize IrType.isNullable, do not use DFS

DFS is not justified for type usages. In contrast to type hierarchies,
traversing the type usage naively with recursion has linear, not
exponential, complexity.
This commit is contained in:
Alexander Udalov
2020-06-11 22:39:25 +02:00
parent 597bc061e2
commit 3c90e25cb4
@@ -11,15 +11,11 @@ import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.buildTypeProjection
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
fun IrClassifierSymbol.superTypes() = when (this) { fun IrClassifierSymbol.superTypes() = when (this) {
@@ -80,22 +76,16 @@ fun Collection<IrType>.commonSupertype(irBuiltIns: IrBuiltIns): IrType {
} }
} }
fun IrType.isNullable(): Boolean = DFS.ifAny( fun IrType.isNullable(): Boolean =
listOf(this), when (this) {
{ is IrSimpleType -> when (val classifier = classifier) {
when (val classifier = it.classifierOrNull) { is IrClassSymbol -> hasQuestionMark
is IrTypeParameterSymbol -> classifier.owner.superTypes is IrTypeParameterSymbol -> hasQuestionMark || classifier.owner.superTypes.any(IrType::isNullable)
is IrClassSymbol -> emptyList()
null -> emptyList()
else -> error("Unsupported classifier: $classifier") else -> error("Unsupported classifier: $classifier")
} }
}, { is IrDynamicType -> true
when (it) { else -> false
is IrSimpleType -> it.hasQuestionMark
else -> it is IrDynamicType
}
} }
)
val IrType.isBoxedArray: Boolean val IrType.isBoxedArray: Boolean
get() = classOrNull?.owner?.fqNameWhenAvailable == KotlinBuiltIns.FQ_NAMES.array.toSafe() get() = classOrNull?.owner?.fqNameWhenAvailable == KotlinBuiltIns.FQ_NAMES.array.toSafe()