FIR DFA: remove exactNotType

Literally not used for anything anymore. What a waste of CPU time.

...and safeCallBreakInsideDoWhile is broken again. Oh well.
This commit is contained in:
pyos
2022-11-08 21:30:00 +01:00
committed by teamcity
parent 6ee6d019ee
commit 757921e63e
11 changed files with 77 additions and 118 deletions
@@ -91,31 +91,18 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
}
}
// ------------------------------- Util functions -------------------------------
private fun foldStatements(statements: Collection<TypeStatement>, all: Boolean): TypeStatement {
require(statements.isNotEmpty())
statements.singleOrNull()?.let { return it }
val variable = statements.first().variable
assert(statements.all { it.variable == variable })
// TypeStatement(variable, exactType, exactNotType) =
// variable is intersect(exactType) && variable !is intersect(exactNotType)
// So `and` of two type statements computes `and` of exactType and `or` of `exactNotType`,
// while `or` is the opposite.
return if (all) {
val exactType = statements.flatMapTo(mutableSetOf()) { it.exactType }
// variable !is a && variable !is b =/=> variable !is commonSuperType(a, b)
// So in this case we can only take the union if either type is a subtype of the other.
val exactNotType = unifyTypes(statements.map { it.exactNotType }, onlyInputTypes = true)
MutableTypeStatement(variable, exactType, exactNotType?.let { mutableSetOf(it) } ?: mutableSetOf())
} else {
val exactType = unifyTypes(statements.map { it.exactType }, onlyInputTypes = false)
val exactNotType = statements.flatMapTo(mutableSetOf()) { it.exactNotType }
MutableTypeStatement(variable, exactType?.let { mutableSetOf(it) } ?: mutableSetOf(), exactNotType)
private inline fun Collection<TypeStatement>.singleOrNew(exactType: () -> MutableSet<ConeKotlinType>): TypeStatement =
when (size) {
0 -> throw AssertionError("need at least one statement")
1 -> first()
else -> {
val variable = first().variable
assert(all { it.variable == variable }) { "folding statements for different variables" }
MutableTypeStatement(variable, exactType())
}
}
}
private fun unifyTypes(types: Collection<Set<ConeKotlinType>>, onlyInputTypes: Boolean): ConeKotlinType? {
private fun unifyTypes(types: Collection<Set<ConeKotlinType>>): ConeKotlinType? {
if (types.any { it.isEmpty() }) return null
val intersected = types.map { ConeTypeIntersector.intersectTypes(context, it.toList()) }
val unified = context.commonSuperTypeOrNull(intersected) ?: return null
@@ -123,14 +110,14 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
unified.isAcceptableForSmartcast() -> unified
unified.canBeNull -> null
else -> context.anyType()
}.takeIf { !onlyInputTypes || it in intersected }
}
}
protected fun and(statements: Collection<TypeStatement>): TypeStatement =
foldStatements(statements, all = true)
statements.singleOrNew { statements.flatMapTo(mutableSetOf()) { it.exactType } }
protected fun or(statements: Collection<TypeStatement>): TypeStatement =
foldStatements(statements, all = false)
statements.singleOrNew { unifyTypes(statements.map { it.exactType })?.let { mutableSetOf(it) } ?: mutableSetOf() }
}
/*
@@ -16,7 +16,6 @@ import kotlin.math.max
data class PersistentTypeStatement(
override val variable: RealVariable,
override val exactType: PersistentSet<ConeKotlinType>,
override val exactNotType: PersistentSet<ConeKotlinType>
) : TypeStatement()
typealias PersistentApprovedTypeStatements = PersistentMap<RealVariable, PersistentTypeStatement>
@@ -391,7 +390,7 @@ private fun lowestCommonFlow(left: PersistentFlow, right: PersistentFlow): Persi
private fun TypeStatement.toPersistent(): PersistentTypeStatement = when (this) {
is PersistentTypeStatement -> this
else -> PersistentTypeStatement(variable, exactType.toPersistentSet(), exactNotType.toPersistentSet())
else -> PersistentTypeStatement(variable, exactType.toPersistentSet())
}
@JvmName("replaceVariableInStatements")
@@ -436,5 +435,5 @@ private fun Statement.replaceVariable(from: RealVariable, to: RealVariable): Sta
if (variable != from) this else when (this) {
is OperationStatement -> copy(variable = to)
is PersistentTypeStatement -> copy(variable = to)
is MutableTypeStatement -> MutableTypeStatement(to, exactType, exactNotType)
is MutableTypeStatement -> MutableTypeStatement(to, exactType)
}
@@ -15,9 +15,8 @@ import kotlin.contracts.contract
class MutableTypeStatement(
override val variable: RealVariable,
override val exactType: MutableSet<ConeKotlinType> = linkedSetOf(),
override val exactNotType: MutableSet<ConeKotlinType> = linkedSetOf()
) : TypeStatement() {
fun copy(): MutableTypeStatement = MutableTypeStatement(variable, LinkedHashSet(exactType), LinkedHashSet(exactNotType))
fun copy(): MutableTypeStatement = MutableTypeStatement(variable, LinkedHashSet(exactType))
}
fun Implication.invertCondition(): Implication = Implication(condition.invert(), effect)
@@ -49,25 +48,7 @@ infix fun DataFlowVariable.notEq(constant: Boolean?): OperationStatement {
infix fun OperationStatement.implies(effect: Statement): Implication = Implication(this, effect)
infix fun RealVariable.typeEq(type: ConeKotlinType): MutableTypeStatement =
MutableTypeStatement(this) andTypeEq type
infix fun RealVariable.typeNotEq(type: ConeKotlinType): MutableTypeStatement =
MutableTypeStatement(this) andTypeNotEq type
infix fun MutableTypeStatement.andTypeEq(type: ConeKotlinType): MutableTypeStatement =
this.apply {
if (type !is ConeErrorType) {
exactType += type
}
}
infix fun MutableTypeStatement.andTypeNotEq(type: ConeKotlinType): MutableTypeStatement =
this.apply {
require(exactNotType.isEmpty()) { "statement $this already has a negation; use `logicSystem.and`" }
if (type !is ConeErrorType) {
exactNotType += type
}
}
MutableTypeStatement(this, if (type is ConeErrorType) linkedSetOf() else linkedSetOf(type))
// --------------------------------------- Utils ---------------------------------------
@@ -31,16 +31,15 @@ data class OperationStatement(override val variable: DataFlowVariable, val opera
sealed class TypeStatement : Statement() {
abstract override val variable: RealVariable
abstract val exactType: Set<ConeKotlinType>
abstract val exactNotType: Set<ConeKotlinType>
val isEmpty: Boolean
get() = exactType.isEmpty() && exactNotType.isEmpty()
get() = exactType.isEmpty()
val isNotEmpty: Boolean
get() = !isEmpty
override fun toString(): String {
return "$variable: $exactType, $exactNotType"
return "$variable: $exactType"
}
}