Assertions on approximation of platform types to non-null types

- for most expressions (ExpressionCodegen.genQualified)
This commit is contained in:
Andrey Breslav
2014-10-05 22:18:15 +04:00
parent 3d5d3e00e3
commit f1c66fa6b0
11 changed files with 193 additions and 24 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.types
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import org.jetbrains.jet.lang.types.Approximation.DataFlowExtras
public trait Flexibility : TypeCapability {
// lowerBound is a subtype of upperBound
@@ -29,15 +30,49 @@ public fun JetType.isFlexible(): Boolean = this.getCapability(javaClass<Flexibil
public fun JetType.flexibility(): Flexibility = this.getCapability(javaClass<Flexibility>())!!
public fun JetType.lowerIfFlexible(): JetType = if (this.isFlexible()) this.flexibility().getLowerBound() else this
public fun JetType.upperIfFlexible(): JetType = if (this.isFlexible()) this.flexibility().getUpperBound() else this
public trait NullAwareness : TypeCapability {
public fun makeNullableAsSpecified(nullable: Boolean): JetType
}
public trait Approximation : TypeCapability {
public class Info(val from: JetType, val to: JetType, val message: String)
public trait DataFlowExtras {
object EMPTY : DataFlowExtras {
override val canBeNull: Boolean get() = true
override val possibleTypes: Set<JetType> get() = setOf()
override val presentableText: String = "<unknown>"
}
class OnlyMessage(message: String) : DataFlowExtras {
override val canBeNull: Boolean get() = true
override val possibleTypes: Set<JetType> get() = setOf()
override val presentableText: String = message
}
val canBeNull: Boolean
val possibleTypes: Set<JetType>
val presentableText: String
}
public fun approximateToExpectedType(expectedType: JetType, dataFlowExtras: DataFlowExtras): Info?
}
fun Approximation.Info.assertNotNull(): Boolean {
return from.upperIfFlexible().isNullable() && !TypeUtils.isNullableType(to)
}
public fun JetType.getApproximationTo(
expectedType: JetType,
extras: Approximation.DataFlowExtras = Approximation.DataFlowExtras.EMPTY
): Approximation.Info? = this.getCapability(javaClass<Approximation>())?.approximateToExpectedType(expectedType, extras)
public open class DelegatingFlexibleType protected (
private val _lowerBound: JetType,
private val _upperBound: JetType
) : DelegatingType(), NullAwareness, Flexibility {
) : DelegatingType(), NullAwareness, Flexibility, Approximation {
class object {
public fun create(lowerBound: JetType, upperBound: JetType): JetType {
if (lowerBound == upperBound) return lowerBound
@@ -65,6 +100,20 @@ public open class DelegatingFlexibleType protected (
return create(TypeUtils.makeNullableAsSpecified(_lowerBound, nullable), TypeUtils.makeNullableAsSpecified(_upperBound, nullable))
}
override fun approximateToExpectedType(expectedType: JetType, dataFlowExtras: Approximation.DataFlowExtras): Approximation.Info? {
// val foo: Any? = foo() : Foo!
if (JetTypeChecker.DEFAULT.isSubtypeOf(getUpperBound(), expectedType)) return null
// if (foo : Foo! != null) {
// val bar: Any = foo
// }
if (!dataFlowExtras.canBeNull && JetTypeChecker.DEFAULT.isSubtypeOf(TypeUtils.makeNotNullable(getUpperBound()), expectedType)) return null
// TODO: maybe check possibleTypes to avoid extra approximations
return Approximation.Info(this, expectedType, dataFlowExtras.presentableText)
}
override fun getDelegate() = _lowerBound
override fun toString() = "('$_lowerBound'..'$_upperBound')"
@@ -37,6 +37,13 @@ public class Intrinsics {
throw new KotlinNullPointerException();
}
public static void checkExpressionValueIsNotNull(Object value, String message) {
if (value == null) {
IllegalStateException exception = new IllegalStateException(message + " must not be null");
throw sanitizeStackTrace(exception);
}
}
public static void checkReturnedValueIsNotNull(Object value, String className, String methodName) {
if (value == null) {
IllegalStateException exception =