Fix language features in tests for gradual migration to 1.3 (part 2)

In 1.3, due to changes in language, testdata for some tests can be
different from 1.2

We want to simlultaneously test both versions, so instead of fixing
language version in such tests, we split them into two: one with fixed
1.2, another with fixed 1.3
This commit is contained in:
Dmitry Savvinov
2018-06-22 11:23:52 +03:00
parent 6d733ff7b9
commit 5cb949ad7f
71 changed files with 1637 additions and 99 deletions
@@ -0,0 +1,151 @@
== s ==
val s = mutableListOf<String>()
---------------------
L0:
1 <START>
v(val s = mutableListOf<String>())
mark(mutableListOf<String>())
magic[UNRESOLVED_CALL](mutableListOf<String>()|!<v0>) -> <v1>
w(s|<v1>)
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== test ==
fun test(name: String?, flag: Boolean): Boolean {
try {
name?.let {
if (flag) {
s.add(it)
}
else {
s.remove(it)
}
return true
}
return false
} finally {
name?.hashCode()
}
}
---------------------
L0:
1 <START>
v(name: String?)
magic[FAKE_INITIALIZER](name: String?) -> <v0>
w(name|<v0>)
v(flag: Boolean)
magic[FAKE_INITIALIZER](flag: Boolean) -> <v1>
w(flag|<v1>)
2 mark({ try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() } })
mark(try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() })
jmp?(L2) NEXT:[mark({ name?.hashCode() }), mark({ name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false })]
3 mark({ name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false })
mark(name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true })
jf(L3) NEXT:[jmp?(L2), r(name) -> <v2>]
r(name) -> <v2>
mark({ if (flag) { s.add(it) } else { s.remove(it) } return true })
r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3>
mark(let { if (flag) { s.add(it) } else { s.remove(it) } return true })
call(let { if (flag) { s.add(it) } else { s.remove(it) } return true }, let|<v2>, <v3>)
L4 [before inlined declaration]:
inlined({ if (flag) { s.add(it) } else { s.remove(it) } return true }) NEXT:[<SINK>]
L3 [result of call]:
L5 [after inlined declaration]:
jmp?(L2) NEXT:[mark({ name?.hashCode() }), r(false) -> <v5>] PREV:[jf(L3)]
r(false) -> <v5>
6 mark({ name?.hashCode() })
mark(name?.hashCode())
jf(L13) NEXT:[ret(*|<v5>) L1, r(name) -> <v11>]
r(name) -> <v11>
mark(hashCode())
call(hashCode(), hashCode|<v11>) -> <v12>
L13 [copy of L11, result of call]:
3 ret(*|<v5>) L1 NEXT:[<END>] PREV:[jf(L13), call(hashCode(), hashCode|<v11>) -> <v12>]
- 2 jmp?(L2) NEXT:[mark({ name?.hashCode() }), jmp(L14)] PREV:[]
- jmp(L14) NEXT:[mark({ name?.hashCode() })] PREV:[]
L2 [onExceptionToFinallyBlock]:
6 mark({ name?.hashCode() }) PREV:[jmp?(L2), jmp?(L2)]
mark(name?.hashCode())
jf(L15) NEXT:[jmp(error), r(name) -> <v11>]
r(name) -> <v11>
mark(hashCode())
call(hashCode(), hashCode|<v11>) -> <v12>
L15 [copy of L11, result of call]:
2 jmp(error) NEXT:[<ERROR>] PREV:[jf(L15), call(hashCode(), hashCode|<v11>) -> <v12>]
L14 [skipFinallyToErrorBlock]:
- 6 mark({ name?.hashCode() }) PREV:[]
- mark(name?.hashCode()) PREV:[]
- jf(L16) NEXT:[merge(try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() }|!<v6>) -> <v7>, r(name) -> <v11>] PREV:[]
- r(name) -> <v11> PREV:[]
- mark(hashCode()) PREV:[]
- call(hashCode(), hashCode|<v11>) -> <v12> PREV:[]
L16 [copy of L11, result of call]:
- 2 merge(try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() }|!<v6>) -> <v7> PREV:[]
L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v10>) L1, ret(*|<v5>) L1]
error:
<ERROR> PREV:[jmp(error)]
sink:
<SINK> PREV:[<ERROR>, <END>, inlined({ if (flag) { s.add(it) } else { s.remove(it) } return true })]
=====================
== inlined anonymous_0 ==
{
if (flag) {
s.add(it)
}
else {
s.remove(it)
}
return true
}
---------------------
L6:
4 <START>
5 mark(if (flag) { s.add(it) } else { s.remove(it) } return true)
mark(if (flag) { s.add(it) } else { s.remove(it) })
r(flag) -> <v0>
jf(L8|<v0>) NEXT:[mark({ s.remove(it) }), mark({ s.add(it) })]
6 mark({ s.add(it) })
mark(s.add(it))
r(s) -> <v1>
r(it) -> <v2>
magic[VALUE_CONSUMER](it|<v2>) -> <v3>
mark(add(it))
call(add(it), <ERROR FUNCTION>|<v1>) -> <v4>
5 jmp(L9) NEXT:[merge(if (flag) { s.add(it) } else { s.remove(it) }|<v4>, <v8>) -> <v9>]
L8 [else branch]:
6 mark({ s.remove(it) }) PREV:[jf(L8|<v0>)]
mark(s.remove(it))
r(s) -> <v5>
r(it) -> <v6>
magic[VALUE_CONSUMER](it|<v6>) -> <v7>
mark(remove(it))
call(remove(it), <ERROR FUNCTION>|<v5>) -> <v8>
L9 ['if' expression result]:
5 merge(if (flag) { s.add(it) } else { s.remove(it) }|<v4>, <v8>) -> <v9> PREV:[jmp(L9), call(remove(it), <ERROR FUNCTION>|<v5>) -> <v8>]
r(true) -> <v10>
L10 [start finally]:
6 mark({ name?.hashCode() })
mark(name?.hashCode())
jf(L11) NEXT:[ret(*|<v10>) L1, r(name) -> <v11>]
r(name) -> <v11>
mark(hashCode())
call(hashCode(), hashCode|<v11>) -> <v12>
L11 [result of call]:
L12 [finish finally]:
5 ret(*|<v10>) L1 NEXT:[<END>] PREV:[jf(L11), call(hashCode(), hashCode|<v11>) -> <v12>]
- 4 ret(*|!<v13>) L7 PREV:[]
L7:
- <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -1,3 +1,4 @@
// !LANGUAGE: +ReadDeserializedContracts +UseCallsInPlaceEffect
// See KT-18698
val s = mutableListOf<String>()
@@ -0,0 +1,68 @@
== s ==
val s = mutableListOf<String>()
---------------------
mutableListOf !<v0>: *
mutableListOf<String>() <v1>: {<: [ERROR : Type for mutableListOf<String>()]} NEW: magic[UNRESOLVED_CALL](mutableListOf<String>()|!<v0>) -> <v1>
=====================
== test ==
fun test(name: String?, flag: Boolean): Boolean {
try {
name?.let {
if (flag) {
s.add(it)
}
else {
s.remove(it)
}
return true
}
return false
} finally {
name?.hashCode()
}
}
---------------------
<v0>: {<: String?} NEW: magic[FAKE_INITIALIZER](name: String?) -> <v0>
<v1>: Boolean NEW: magic[FAKE_INITIALIZER](flag: Boolean) -> <v1>
name <v2>: String NEW: r(name) -> <v2>
{ if (flag) { s.add(it) } else { s.remove(it) } return true } <v3>: {<: (String) -> Nothing} NEW: r({ if (flag) { s.add(it) } else { s.remove(it) } return true }) -> <v3>
let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: *
name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } !<v4>: * COPY
false <v5>: Boolean NEW: r(false) -> <v5>
return false !<v6>: *
{ name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } !<v6>: * COPY
try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() } <v7>: * NEW: merge(try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() }|!<v6>) -> <v7>
{ try { name?.let { if (flag) { s.add(it) } else { s.remove(it) } return true } return false } finally { name?.hashCode() } } <v7>: * COPY
=====================
== inlined anonymous_0 ==
{
if (flag) {
s.add(it)
}
else {
s.remove(it)
}
return true
}
---------------------
<v3>: * NEW: magic[VALUE_CONSUMER](it|<v2>) -> <v3>
<v7>: * NEW: magic[VALUE_CONSUMER](it|<v6>) -> <v7>
flag <v0>: Boolean NEW: r(flag) -> <v0>
s <v1>: * NEW: r(s) -> <v1>
it <v2>: * NEW: r(it) -> <v2>
add(it) <v4>: * NEW: call(add(it), <ERROR FUNCTION>|<v1>) -> <v4>
s.add(it) <v4>: * COPY
{ s.add(it) } <v4>: * COPY
s <v5>: * NEW: r(s) -> <v5>
it <v6>: * NEW: r(it) -> <v6>
remove(it) <v8>: * NEW: call(remove(it), <ERROR FUNCTION>|<v5>) -> <v8>
s.remove(it) <v8>: * COPY
{ s.remove(it) } <v8>: * COPY
if (flag) { s.add(it) } else { s.remove(it) } <v9>: * NEW: merge(if (flag) { s.add(it) } else { s.remove(it) }|<v4>, <v8>) -> <v9>
true <v10>: Boolean NEW: r(true) -> <v10>
return true !<v13>: *
if (flag) { s.add(it) } else { s.remove(it) } return true !<v13>: * COPY
=====================
@@ -0,0 +1,23 @@
// !LANGUAGE: -ReadDeserializedContracts -UseCallsInPlaceEffect
// See KT-18698
val s = mutableListOf<String>()
fun test(name: String?, flag: Boolean): Boolean {
try {
name?.let {
if (flag) {
s.add(it)
}
else {
s.remove(it)
}
return true
}
return false
} finally {
name?.hashCode()
}
}
@@ -0,0 +1,206 @@
== doCall ==
inline fun doCall(f: () -> Unit) = f()
---------------------
L0:
1 <START>
v(f: () -> Unit)
magic[FAKE_INITIALIZER](f: () -> Unit) -> <v0>
w(f|<v0>)
r(f) -> <v1>
mark(f())
call(f(), invoke|<v1>) -> <v2>
ret(*|<v2>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== test1 ==
fun test1(nonLocal: String): String {
val localResult = doCall {
return nonLocal //unreachable
}
return "NON_LOCAL_FAILED $localResult" //unreachable
}
---------------------
L0:
1 <START>
v(nonLocal: String)
magic[FAKE_INITIALIZER](nonLocal: String) -> <v0>
w(nonLocal|<v0>)
2 mark({ val localResult = doCall { return nonLocal //unreachable } return "NON_LOCAL_FAILED $localResult" //unreachable })
v(val localResult = doCall { return nonLocal //unreachable })
mark({ return nonLocal //unreachable })
jmp?(L2) NEXT:[r({ return nonLocal //unreachable }) -> <v1>, d({ return nonLocal //unreachable })]
d({ return nonLocal //unreachable }) NEXT:[<SINK>]
L2 [after local declaration]:
r({ return nonLocal //unreachable }) -> <v1> PREV:[jmp?(L2)]
mark(doCall { return nonLocal //unreachable })
call(doCall { return nonLocal //unreachable }, doCall|<v1>) -> <v2>
w(localResult|<v2>)
mark("NON_LOCAL_FAILED $localResult")
r(localResult) -> <v3>
magic[STRING_TEMPLATE]("NON_LOCAL_FAILED $localResult"|<v3>) -> <v4>
ret(*|<v4>) L1
L1:
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v4>) L1]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d({ return nonLocal //unreachable })]
=====================
== anonymous_0 ==
{
return nonLocal //unreachable
}
---------------------
L3:
3 <START>
4 mark(return nonLocal //unreachable)
r(nonLocal) -> <v0>
ret(*|<v0>) L1 NEXT:[<END>]
L4:
3 <END> NEXT:[<SINK>] PREV:[]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== doSomething ==
fun doSomething() {}
---------------------
L0:
1 <START>
2 mark({})
read (Unit)
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== test2 ==
fun test2() {
fun f(x: Any?) = x
f(null?.let { return })
// false unreachable here
doSomething()
}
---------------------
L0:
1 <START>
2 mark({ fun f(x: Any?) = x f(null?.let { return }) // false unreachable here doSomething() })
jmp?(L2) NEXT:[mark(null?.let { return }), d(fun f(x: Any?) = x)]
d(fun f(x: Any?) = x) NEXT:[<SINK>]
L2 [after local declaration]:
mark(null?.let { return }) PREV:[jmp?(L2)]
jf(L5) NEXT:[mark(f(null?.let { return })), r(null) -> <v0>]
r(null) -> <v0>
mark({ return })
r({ return }) -> <v1>
mark(let { return })
call(let { return }, let|<v0>, <v1>)
L6 [before inlined declaration]:
inlined({ return }) NEXT:[<SINK>]
L5 [result of call]:
L7 [after inlined declaration]:
mark(f(null?.let { return })) PREV:[jf(L5)]
call(f(null?.let { return }), f|!<v2>) -> <v3>
mark(doSomething())
call(doSomething(), doSomething) -> <v4>
L1:
1 <END> NEXT:[<SINK>] PREV:[ret L1, call(doSomething(), doSomething) -> <v4>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, d(fun f(x: Any?) = x), inlined({ return })]
=====================
== f ==
fun f(x: Any?) = x
---------------------
L3:
3 <START>
v(x: Any?)
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
r(x) -> <v1>
ret(*|<v1>) L4
L4:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== inlined anonymous_1 ==
{ return }
---------------------
L8:
3 <START>
4 mark(return)
ret L1 NEXT:[<END>]
- 3 ret(*|!<v0>) L9 PREV:[]
L9:
- <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
== test3 ==
fun test3(x: Any?): Boolean =
x?.let {
return true
} ?: false
---------------------
L0:
1 <START>
v(x: Any?)
magic[FAKE_INITIALIZER](x: Any?) -> <v0>
w(x|<v0>)
mark(x?.let { return true })
jf(L2) NEXT:[mark(x?.let { return true } ?: false), r(x) -> <v1>]
r(x) -> <v1>
mark({ return true })
r({ return true }) -> <v2>
mark(let { return true })
call(let { return true }, let|<v1>, <v2>)
L3 [before inlined declaration]:
inlined({ return true }) NEXT:[<SINK>]
L2 [result of call]:
L4 [after inlined declaration]:
mark(x?.let { return true } ?: false) PREV:[jf(L2)]
jt(L7|!<v3>) NEXT:[r(false) -> <v4>, merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>]
r(false) -> <v4>
L7 [after elvis operator]:
merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5> PREV:[jt(L7|!<v3>), r(false) -> <v4>]
ret(*|<v5>) L1
L1:
<END> NEXT:[<SINK>] PREV:[ret(*|<v0>) L1, ret(*|<v5>) L1]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>, inlined({ return true })]
=====================
== inlined anonymous_2 ==
{
return true
}
---------------------
L5:
2 <START>
3 mark(return true)
r(true) -> <v0>
ret(*|<v0>) L1 NEXT:[<END>]
- 2 ret(*|!<v1>) L6 PREV:[]
L6:
- <END> NEXT:[<SINK>] PREV:[]
error:
- <ERROR> PREV:[]
sink:
- <SINK> PREV:[]
=====================
@@ -1,3 +1,4 @@
// !LANGUAGE: +ReadDeserializedContracts +UseCallsInPlaceEffect
// See also KT-5198 / KT-10186
inline fun doCall(f: () -> Unit) = f()
@@ -20,6 +21,6 @@ fun test2() {
}
fun test3(x: Any?): Boolean =
x?.let {
x?.let {
return true
} ?: false
@@ -0,0 +1,88 @@
== doCall ==
inline fun doCall(f: () -> Unit) = f()
---------------------
<v0>: {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](f: () -> Unit) -> <v0>
f <v1>: {<: () -> Unit} NEW: r(f) -> <v1>
f() <v2>: Unit NEW: call(f(), invoke|<v1>) -> <v2>
=====================
== test1 ==
fun test1(nonLocal: String): String {
val localResult = doCall {
return nonLocal //unreachable
}
return "NON_LOCAL_FAILED $localResult" //unreachable
}
---------------------
<v0>: String NEW: magic[FAKE_INITIALIZER](nonLocal: String) -> <v0>
{ return nonLocal //unreachable } <v1>: {<: () -> Unit} NEW: r({ return nonLocal //unreachable }) -> <v1>
doCall { return nonLocal //unreachable } <v2>: Unit NEW: call(doCall { return nonLocal //unreachable }, doCall|<v1>) -> <v2>
localResult <v3>: * NEW: r(localResult) -> <v3>
"NON_LOCAL_FAILED $localResult" <v4>: String NEW: magic[STRING_TEMPLATE]("NON_LOCAL_FAILED $localResult"|<v3>) -> <v4>
return "NON_LOCAL_FAILED $localResult" !<v5>: *
{ val localResult = doCall { return nonLocal //unreachable } return "NON_LOCAL_FAILED $localResult" //unreachable } !<v5>: * COPY
=====================
== anonymous_0 ==
{
return nonLocal //unreachable
}
---------------------
nonLocal <v0>: String NEW: r(nonLocal) -> <v0>
return nonLocal !<v1>: *
return nonLocal //unreachable !<v1>: * COPY
=====================
== doSomething ==
fun doSomething() {}
---------------------
=====================
== test2 ==
fun test2() {
fun f(x: Any?) = x
f(null?.let { return })
// false unreachable here
doSomething()
}
---------------------
null <v0>: Nothing NEW: r(null) -> <v0>
{ return } <v1>: {<: (Nothing) -> Nothing} NEW: r({ return }) -> <v1>
let { return } !<v2>: *
null?.let { return } !<v2>: * COPY
f(null?.let { return }) <v3>: * NEW: call(f(null?.let { return }), f|!<v2>) -> <v3>
doSomething() <v4>: * NEW: call(doSomething(), doSomething) -> <v4>
{ fun f(x: Any?) = x f(null?.let { return }) // false unreachable here doSomething() } <v4>: * COPY
=====================
== f ==
fun f(x: Any?) = x
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: * NEW: r(x) -> <v1>
=====================
== inlined anonymous_1 ==
{ return }
---------------------
return !<v0>: *
return !<v0>: * COPY
=====================
== test3 ==
fun test3(x: Any?): Boolean =
x?.let {
return true
} ?: false
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](x: Any?) -> <v0>
x <v1>: {<: Any} NEW: r(x) -> <v1>
{ return true } <v2>: {<: (Any) -> Nothing} NEW: r({ return true }) -> <v2>
let { return true } !<v3>: *
x?.let { return true } !<v3>: * COPY
false <v4>: Boolean NEW: r(false) -> <v4>
x?.let { return true } ?: false <v5>: Boolean NEW: merge(x?.let { return true } ?: false|!<v3>, <v4>) -> <v5>
=====================
== inlined anonymous_2 ==
{
return true
}
---------------------
true <v0>: Boolean NEW: r(true) -> <v0>
return true !<v1>: *
return true !<v1>: * COPY
=====================
+26
View File
@@ -0,0 +1,26 @@
// !LANGUAGE: -ReadDeserializedContracts -UseCallsInPlaceEffect
// See also KT-5198 / KT-10186
inline fun doCall(f: () -> Unit) = f()
fun test1(nonLocal: String): String {
val localResult = doCall {
return nonLocal //unreachable
}
return "NON_LOCAL_FAILED $localResult" //unreachable
}
fun doSomething() {}
fun test2() {
fun f(x: Any?) = x
f(null?.let { return })
// false unreachable here
doSomething()
}
fun test3(x: Any?): Boolean =
x?.let {
return true
} ?: false