Skip to content

Commit 99ac0ce

Browse files
committed
ControlFlowInfoSelfTypes test
1 parent 0ef568a commit 99ac0ce

File tree

9 files changed

+255
-0
lines changed

9 files changed

+255
-0
lines changed

compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// TARGET_BACKEND: JVM_IR
2+
// IGNORE_BACKEND: JVM_IR
3+
4+
// WITH_STDLIB
5+
6+
import kotlin.Self
7+
8+
interface ReadOnlyControlFlowInfo<K : Any, D : Any> {
9+
fun getOrNull(key: K): D?
10+
11+
// Only used in tests
12+
fun asMap(): Map<K, D>
13+
}
14+
15+
@Self
16+
abstract class ControlFlowInfo<K : Any, D : Any>
17+
internal constructor(
18+
protected val map: Map<K, D> = mapOf()
19+
) : Map<K, D> by map, ReadOnlyControlFlowInfo<K, D> {
20+
protected abstract fun copy(newMap: Map<K, D>): Self
21+
22+
fun put(key: K, value: D): Self =
23+
put(key, value, this[key] ?: null as D?)
24+
25+
/**
26+
* This overload exists just for sake of optimizations: in some cases we've just retrieved the old value,
27+
* so we don't need to scan through the persistent hashmap again
28+
*/
29+
fun put(key: K, value: D, oldValue: D?): Self {
30+
// Avoid a copy instance creation if new value is the same
31+
if (value == oldValue) return this as Self
32+
val newMap = map + (key to value)
33+
return copy(newMap)
34+
}
35+
36+
override fun getOrNull(key: K): D? = this[key] ?: null as D?
37+
override fun asMap() = this
38+
39+
fun retainAll(predicate: (K) -> Boolean): Self {
40+
val newMap = map.filter { predicate(it.key) }
41+
return copy(newMap)
42+
}
43+
44+
override fun equals(other: Any?) = map == (other as? ControlFlowInfo<*, *, *>)?.map
45+
46+
override fun hashCode() = map.hashCode()
47+
48+
override fun toString() = map.toString()
49+
}
50+
51+
// ALIASES BEGIN
52+
53+
typealias VariableDescriptor = String
54+
typealias VariableUsageControlFlowInfo<S, D> = ControlFlowInfo<VariableDescriptor, D, S>
55+
typealias VariableUsageReadOnlyControlInfo = ReadOnlyControlFlowInfo<VariableDescriptor, VariableUseState>
56+
57+
// ALIASES END
58+
59+
60+
// IMPLEMENTATIONS OF CONTROL FLOW INFOS BEGIN
61+
62+
class UsageVariableControlFlowInfo(map: Map<VariableDescriptor, VariableUseState> = mapOf()) :
63+
VariableUsageControlFlowInfo<UsageVariableControlFlowInfo, VariableUseState>(map),
64+
VariableUsageReadOnlyControlInfo {
65+
override fun copy(newMap: Map<VariableDescriptor, VariableUseState>): UsageVariableControlFlowInfo =
66+
UsageVariableControlFlowInfo(newMap)
67+
}
68+
69+
interface VariableInitReadOnlyControlFlowInfo :
70+
ReadOnlyControlFlowInfo<VariableDescriptor, VariableControlFlowState> {
71+
fun checkDefiniteInitializationInWhen(merge: VariableInitReadOnlyControlFlowInfo): Boolean
72+
}
73+
74+
class VariableInitControlFlowInfo(map: Map<VariableDescriptor, VariableControlFlowState> = mapOf()) :
75+
VariableUsageControlFlowInfo<VariableInitControlFlowInfo, VariableControlFlowState>(map),
76+
VariableInitReadOnlyControlFlowInfo {
77+
override fun copy(newMap: Map<VariableDescriptor, VariableControlFlowState>): VariableInitControlFlowInfo =
78+
VariableInitControlFlowInfo(newMap)
79+
80+
// this = output of EXHAUSTIVE_WHEN_ELSE instruction
81+
// merge = input of MergeInstruction
82+
// returns true if definite initialization in when happens here
83+
override fun checkDefiniteInitializationInWhen(merge: VariableInitReadOnlyControlFlowInfo): Boolean {
84+
for ((key, value) in iterator()) {
85+
if (value.initState == InitState.INITIALIZED_EXHAUSTIVELY &&
86+
merge.getOrNull(key)?.initState == InitState.INITIALIZED
87+
) {
88+
return true
89+
}
90+
}
91+
return false
92+
}
93+
}
94+
95+
// IMPLEMENTATIONS OF CONTROL FLOW INFOS END
96+
97+
// STATES BEGIN
98+
99+
class VariableControlFlowState private constructor(val initState: InitState, val isDeclared: Boolean) {
100+
101+
fun definitelyInitialized(): Boolean = initState == InitState.INITIALIZED
102+
103+
fun mayBeInitialized(): Boolean = initState != InitState.NOT_INITIALIZED
104+
105+
override fun toString(): String {
106+
if (initState == InitState.NOT_INITIALIZED && !isDeclared) return "-"
107+
return "$initState${if (isDeclared) "D" else ""}"
108+
}
109+
110+
companion object {
111+
112+
private val VS_IT = VariableControlFlowState(InitState.INITIALIZED, true)
113+
private val VS_IF = VariableControlFlowState(InitState.INITIALIZED, false)
114+
private val VS_ET = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, true)
115+
private val VS_EF = VariableControlFlowState(InitState.INITIALIZED_EXHAUSTIVELY, false)
116+
private val VS_UT = VariableControlFlowState(InitState.UNKNOWN, true)
117+
private val VS_UF = VariableControlFlowState(InitState.UNKNOWN, false)
118+
private val VS_NT = VariableControlFlowState(InitState.NOT_INITIALIZED, true)
119+
private val VS_NF = VariableControlFlowState(InitState.NOT_INITIALIZED, false)
120+
121+
fun create(initState: InitState, isDeclared: Boolean): VariableControlFlowState =
122+
when (initState) {
123+
InitState.INITIALIZED -> if (isDeclared) VS_IT else VS_IF
124+
InitState.INITIALIZED_EXHAUSTIVELY -> if (isDeclared) VS_ET else VS_EF
125+
InitState.UNKNOWN -> if (isDeclared) VS_UT else VS_UF
126+
InitState.NOT_INITIALIZED -> if (isDeclared) VS_NT else VS_NF
127+
}
128+
129+
fun createInitializedExhaustively(isDeclared: Boolean): VariableControlFlowState =
130+
create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared)
131+
132+
fun create(isInitialized: Boolean, isDeclared: Boolean = false): VariableControlFlowState =
133+
create(if (isInitialized) InitState.INITIALIZED else InitState.NOT_INITIALIZED, isDeclared)
134+
135+
fun create(isDeclaredHere: Boolean, mergedEdgesData: VariableControlFlowState?): VariableControlFlowState =
136+
create(true, isDeclaredHere || mergedEdgesData != null && mergedEdgesData.isDeclared)
137+
}
138+
}
139+
140+
enum class VariableUseState(private val priority: Int) {
141+
READ(3),
142+
WRITTEN_AFTER_READ(2),
143+
ONLY_WRITTEN_NEVER_READ(1),
144+
UNUSED(0);
145+
146+
fun merge(variableUseState: VariableUseState?): VariableUseState {
147+
if (variableUseState == null || priority > variableUseState.priority) return this
148+
return variableUseState
149+
}
150+
151+
companion object {
152+
153+
@JvmStatic
154+
fun isUsed(variableUseState: VariableUseState?): Boolean =
155+
variableUseState != null && variableUseState != UNUSED
156+
}
157+
}
158+
159+
enum class InitState(private val s: String) {
160+
// Definitely initialized
161+
INITIALIZED("I"),
162+
// Fake initializer in else branch of "exhaustive when without else", see MagicKind.EXHAUSTIVE_WHEN_ELSE
163+
INITIALIZED_EXHAUSTIVELY("IE"),
164+
// Initialized in some branches, not initialized in other branches
165+
UNKNOWN("I?"),
166+
// Definitely not initialized
167+
NOT_INITIALIZED("");
168+
169+
fun merge(other: InitState): InitState {
170+
// X merge X = X
171+
// X merge IE = IE merge X = X
172+
// else X merge Y = I?
173+
if (this == other || other == INITIALIZED_EXHAUSTIVELY) return this
174+
if (this == INITIALIZED_EXHAUSTIVELY) return other
175+
return UNKNOWN
176+
}
177+
178+
override fun toString() = s
179+
}
180+
181+
// STATES END
182+
183+
fun box(): String {
184+
val usageVariableControlFlowInfo: UsageVariableControlFlowInfo = UsageVariableControlFlowInfo(
185+
mapOf(
186+
"unused" to VariableUseState.UNUSED,
187+
"read" to VariableUseState.READ
188+
)
189+
)
190+
191+
val usageVariableControlFlowInfoUpdated: UsageVariableControlFlowInfo =
192+
usageVariableControlFlowInfo.put("second unused", VariableUseState.UNUSED)
193+
194+
195+
val variableInitControlFlowInfo: VariableInitControlFlowInfo = VariableInitControlFlowInfo(
196+
mapOf(
197+
"VS_IT" to VariableControlFlowState.create(InitState.INITIALIZED, isDeclared = true),
198+
"VS_IF" to VariableControlFlowState.create(InitState.INITIALIZED, isDeclared = false)
199+
)
200+
)
201+
202+
val updatedVariableInitControlFlowInfo = variableInitControlFlowInfo.put(
203+
"VS_ET", VariableControlFlowState.create(InitState.INITIALIZED_EXHAUSTIVELY, isDeclared = true)
204+
)
205+
206+
val predicate = usageVariableControlFlowInfoUpdated.containsKey("second unused") && updatedVariableInitControlFlowInfo.containsKey("VS_ET")
207+
208+
return if (predicate) "OK" else "ERROR"
209+
}

compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)