Assertions on approximation of platform types to non-null types
- for most expressions (ExpressionCodegen.genQualified)
This commit is contained in:
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user