JS_IR: fix typecheck corner case

Consider `fun <E : I> foo(a: Any?) = a as? E`, where I is an interface.
This check used to fail, because the `a == null` was missing, and
the `isInterface` stdlib method crashes if the first argument
is null. This change adds the null check.

Also this change prettifies the instance check in case of type parameter
left operand.
This commit is contained in:
Anton Bannykh
2019-12-13 18:29:22 +03:00
committed by Anton Bannykh
parent 9a971172c9
commit d6fcde7316
10 changed files with 47 additions and 5 deletions
@@ -41,7 +41,7 @@ private fun IrType.isClassWithNamePrefix(prefix: String, packageFqName: FqName):
return parent.fqName == packageFqName
}
private fun IrType.superTypes(): List<IrType> = classifierOrNull?.superTypes() ?: emptyList()
fun IrType.superTypes(): List<IrType> = classifierOrNull?.superTypes() ?: emptyList()
fun IrType.isFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isFunction)
fun IrType.isSuspendFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isSuspendFunction)
@@ -151,6 +151,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
// Note: native `instanceOf` is not used which is important because of null-behaviour
private fun advancedCheckRequired(type: IrType) = type.isInterface() ||
type.isTypeParameter() && type.superTypes().any { it.isInterface() } ||
type.isArray() ||
type.isPrimitiveArray() ||
isTypeOfCheckingType(type)
@@ -261,10 +262,16 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
// TODO either remove functions with reified type parameters or support this case
// assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
return typeParameter.superTypes.fold(litTrue) { r, t ->
return typeParameter.superTypes.fold<IrType, IrExpression?>(null) { r, t ->
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull())
calculator.and(r, check)
}
if (r == null) {
check
} else {
calculator.andand(r, check)
}
} ?: litTrue
}
// private fun generateCheckForChar(argument: IrExpression) =