1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-15 04:32:21 +00:00
ton/tolk-tester/tests/smart-cast-tests.tolk
2025-02-11 22:52:01 +04:00

639 lines
18 KiB
Text

// the goal of this file is not only to @testcase results —
// but to check that this file compiles
fun getNullableInt(): int? { return 5; }
fun getNullableSlice(): slice? { return null; }
fun takeNullableInt(a: int?) {}
fun takeNullableSlice(a: slice?) {}
fun increment(mutate self: int) { self += 1; }
fun assignToInt(mutate self: int, value: int) { self = value; }
fun assignToNullableInt(mutate self: int?, value: int) { self = value; }
fun sameTensor(t: (int, int)) { return t; }
fun sameTensor2(t: (int?, (slice, slice, slice, builder)?)) { return t; }
fun eq<T>(v: T) { return v; }
fun getTwo<X>(): X { return 2 as X; }
fun test1(): int {
var x = getNullableInt();
var y = getNullableInt();
if (x != null && y != null) {
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
return -1;
}
fun test2() {
var (x, y) = (getNullableInt(), getNullableInt());
if (x == null || y == null) {
return null;
}
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
fun test3(): int {
var ([x, y]) = [getNullableInt(), getNullableInt()];
if (x != null) {
if (y != null) {
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
return x;
}
if (random() > -1) {
if (y == null) { return -1; }
else { return y; }
}
return 0;
}
fun test4() {
var x = getNullableInt();
if (x != null && x > 0) {
var x = getNullableInt();
if (x != null && x + 10 < 0) {
var x = getNullableInt();
return 10 > 3 && 10 < 10 && x != null && x + 8 > 10;
}
}
if (x != null && x < 1) {
return false;
}
if (x == null && x == null) {
__expect_type(x, "null");
return true;
}
return x < x + 3;
}
fun test5() {
var (a, (b, c)) = (getNullableInt(), (getNullableInt(), getNullableInt()));
if (a == null) { return -1; }
if (!(b != null)) { return -2; }
if (random() ? c == null && c == null : c == null) { return -3; }
return a + b + c;
}
fun test6() {
var a: int? = 5;
__expect_type(a, "int");
takeNullableInt(a);
__expect_type(a, "int");
if (random()) {
a = null;
} else {
if (random()) { a = null; }
else { a = null; }
}
__expect_type(a, "null");
takeNullableSlice(a); // ok, `slice?` is `slice | null`, here a definitely null
var b: int? = null;
__expect_type(b, "null");
takeNullableInt(b);
takeNullableSlice(b); // same reason
var c: int? = 10;
__expect_type(c, "int");
takeNullableSlice(c = null);
}
fun test7() {
var (a, b, c, d) = (getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt());
if (a == null && true) { return -1; }
if (true && true && 1 && !0 && b == null) { return -2; }
if (true ? c == null && c == null && true : false) { return -3; }
if (!true ? random() > 0 : a != null && (d == null && b != null)) { return -4; }
return a + b + c + d;
}
fun test8(x: int?, y: int?) {
var allGt1 = x != null && x > 1 && y != null && y > 1;
var xGtY = x != null && y != null && x > y;
var xLtEq0 = x == null || x < 0;
(x = 0) < random() || x > 10;
return x + 0;
}
fun test9() {
var x = getNullableInt();
var y = getNullableInt();
if (x == null || y == null) {
return -1;
}
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
fun test10(): int {
var (x, y) = (getNullableInt(), getNullableInt());
if (x == null) {
if (y == null) { return -1; }
__expect_type(x, "null");
__expect_type(y, "int");
return y;
}
if (y == null) {
return x;
}
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
fun test11() {
var [x, y] = [getNullableInt(), getNullableInt()];
if (random()) { return x == null || y == null ? -1 : x + y; }
if (true && (x == null || y == null) && !!true) { return 0; }
return x + y;
}
fun test12() {
var (x, y) = (getNullableInt(), getNullableInt());
if (random() ? x == null || y == null : x == null || y == null) { return -1; }
__expect_type(x, "int");
__expect_type(y, "int");
return x + y;
}
fun test13() {
var x: int? = getNullableInt();
var y: int? = 10;
var z = getNullableInt();
var w = getNullableInt();
beginCell().storeInt(x!, 32).storeInt(x = getNullableInt()!, 32).storeInt(x, 32)
.storeInt(y, 32).storeInt(z = 10, 32).storeInt(x + y + z, 32)
.storeInt(w == null ? -1 : w, 32).storeInt(!(null == w) ? w : -1, 32);
}
fun test14() {
var (x, y) = (getNullableInt(), getNullableInt());
if (x == null) {
x = 0;
}
if (y == null) {
if (random()) { return 0; }
else { y = 0; }
}
return x + y;
}
fun test20() {
var t = (getNullableInt(), getNullableInt());
if (t.0 != null && t.1 != null) {
__expect_type(t.0, "int");
__expect_type(t.1, "int");
return t.0 + t.1;
}
t.0 = 10;
if (t.1 == null) {
t.1 = 20;
}
__expect_type(t.0, "int");
__expect_type(t.1, "int");
return t.0 + t.1;
}
fun test21() {
var t = (getNullableInt(), (getNullableInt(), getNullableInt()));
if (t.0 != null && t.1.0 != null) {
if (t.1.1 != null) { return t.0 + t.1.0 + t.1.1; }
return t.0 + t.1.0;
}
if (t.0 != null) {
return t.0 + 0;
}
__expect_type(t.0, "null");
__expect_type(t.1.0, "int?");
return t.1.0 == null ? -1 : t.1.0 + 0;
}
fun test22() {
var t = (getNullableInt(), (getNullableInt(), getNullableInt()));
if (t.0 == null || t.1.0 == null || t.1.1 == null) {
return -1;
}
return t.0 + t.1.0 + t.1.1;
}
@method_id(123)
fun test23() {
var (x: int?, y: int?, z: int?) = (getNullableInt(), getNullableInt(), getNullableInt());
((x = 1, 0).0, (y = 2, 1).0) = (3, z = 4);
return x + y + z;
}
@method_id(124)
fun test24(x: int?) {
if (x == null) {
__expect_type(x, "null");
assignToNullableInt(mutate x, 10);
__expect_type(x, "int?");
x.assignToNullableInt(x! + 5);
} else {
__expect_type(x, "int");
increment(mutate x);
x.increment();
__expect_type(x, "int");
}
__expect_type(x, "int?");
return x;
}
fun test25() {
var x = (getNullableInt(), getNullableInt(), getNullableInt());
x.0 = x.2 = random();
return x.0 + x.2;
}
fun test26() {
var x = [getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(),
getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt()];
if (~(x.0 = random())) { return; }
if ((x.1 = random()) < (x.2 = random())) { return; }
else if (!(x.2 <=> (x.3 = random()))) { return; }
x.5 = (x.4 = random()) ? (x.6 = random()) : (x.6 = random());
if ((x.7 = random()) as int) { return; }
if (((((x.8 = random()) != null)))) { return; }
if ([x.1, (x.9 = random())!].1) { return; }
val result = x.0+x.1+x.2+x.3+x.4+x.5+x.6+x.7+x.8+x.9;
}
fun test27() {
var (x, _) = ([getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(),
getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt()], []);
+(x.0 = random());
x.0 += [((x.1 = random()) < (x.2 = random() + x.1)) as int].0;
!(x.2 <=> (x.3 = random() + x.2));
x.5 = (x.4 = random()) ? (x.6 = random()) : (x.6 = random());
(x.7 = random()) as int;
(((((x.8 = random()) != null))));
[x.1, (x.9 = random())!].1;
return x.0+x.1+x.2+x.3+x.4+x.5+x.6+x.7+x.8+x.9;
}
fun test28() {
var x = (getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt());
__expect_type((x.0 = random(), x.0 += (x.1 = random()) as int, !(x.1 <=> (x.2 = random() + x.0)) == null, (x.3 = random()) ? x.3 : (!x.3) as int),
"(int, int, bool, int)");
}
fun test29() {
var x = (getNullableInt(), getNullableInt(), getNullableInt(), getNullableInt());
__expect_type([x.0 = random(), ((x.0 += (x.1 = random()) as int)), !(x.1 <=> (x.2 = random() + x.0)) == null, (x.3 = random()) ? x.3 : (!x.3) as int],
"[int, int, bool, int]");
}
@method_id(130)
fun test30(initial5: bool) {
var t: (int?, (int?, (int?, int?))) = initial5
? (getNullableInt(), (getNullableInt(), (getNullableInt(), getNullableInt())))
: (null, (null, (null, null)));
if (t.0 == null || t.1.0 == null || t.1.1.0 == null || t.1.1.1 == null) {
if (t.1.0 == null || t.1.1.0 == null) {
if (t.1.1.0 == null) {
t.1.1.0 = 4;
}
__expect_type(t.1.1.0, "int");
__expect_type(t.1.1.1, "int?");
__expect_type(t.1.0, "int?");
t.1.1.1 = 3;
t.1.0 = 2;
__expect_type(t.1.1.1, "int");
__expect_type(t.1.0, "int");
}
if (t.1.1.1 != null) {}
else { t.1.1.1 = 3; }
t.0 = 1;
}
return t.0 + t.1.0 + t.1.1.0 + t.1.1.1;
}
fun test31() {
var t = (getNullableInt(), getNullableInt());
t.0 == null ? (t.0, t.1) = (1, 2) : (t.1, t.0) = (4, 3);
return t.0 + t.1;
}
@method_id(132)
fun test32() {
var t: (int?, (int?, int?)?, (int?, int?)) = (getNullableInt(), (getNullableInt(), getNullableInt()), (getNullableInt(), getNullableInt()));
if (t.0 == null) { return -1; }
t.1 != null && t.1.0 == null ? t.1 = (1, 2) : t.1 = (3, 4);
if (t.2.1 != null) { t.2.0 = 1; t.2.1 = 2; }
else { [t.2.0, t.2.1] = [3, 4]; }
return t.0 + t.1.0! + t.1.1! + t.2.0 + t.2.1;
}
@method_id(133)
fun test33(): int {
var x = getNullableInt();
repeat (eq(x = 5)) {
__expect_type(x, "int");
increment(mutate x);
}
return x;
}
fun test34() {
var (x, y) = (getNullableInt(), getNullableInt());
if (random()) { throw (x = 1, y = 2); }
else { throw (x = 3, y = (1, getNullableInt()!).1); }
return x + y;
}
fun test35() {
var (x, y, z, t) = (getNullableInt(), getNullableInt(), getNullableInt(), (getNullableInt(), getNullableInt()));
assert (x != null, 404);
assert (t.0 != null && true && !(t.1 == null) && !(z = 4)) throw (y = 404);
__expect_type(y, "int?");
return x + t.0 + t.1 + z;
}
fun test36() {
var x = getNullableInt();
assert (x == null, x + 0); // check that x is int there
__expect_type(x, "null");
}
fun test37() {
var (x, code) = (getNullableInt()!, getNullableInt());
try {
} catch(code) {
x = 20;
return x + code; // code is scoped
}
return code == null ? x : x + code;
}
fun assignNull2<T1, T2>(mutate x: T1?, mutate y: T2?) {
x = null;
y = null;
}
fun test38() {
var (x: int?, y: int?) = (1, 2);
__expect_type(x, "int");
__expect_type(y, "int");
assignNull2<int, int>(mutate x, mutate y);
__expect_type(x, "int?");
__expect_type(y, "int?");
if (x != null) {
if (y == null) { return -1; }
return x + y;
}
var t: (int?, slice?) = (null, null);
if (!false) { t.0 = 1; }
if (true) { t.1 = beginCell().endCell().beginParse(); }
__expect_type(t.0, "int");
__expect_type(t.1, "slice");
t.0 + t.1.loadInt(32);
assignNull2(mutate t.0, mutate t.1);
__expect_type(t.0, "int?");
__expect_type(t.1, "slice?");
t.0 != null && t.1 != null ? t.0 + loadInt(mutate t.1, 32) : -1;
return t.0 != null && t.1 != null ? t.0 + loadInt(mutate t.1, 32) : -1;
}
@method_id(139)
fun test39() {
var x: (int?, int?)? = (4, null);
x.1 = 10;
x.1 += 1;
x!.1 += 1;
return (x!.0! + x.1);
}
@method_id(140)
fun test40(second: int?) {
var x: (int?, int?)? = (4, second);
if (x.1 != null) {
val result = x.1 + x!.1 + x!!.1 + x.1! + x!!.1!!;
}
if (x!.1 != null) {
val result = x.1 + x!.1 + x!!.1 + x.1! + x!!.1!!;
}
if (!(x!!.1 != null)) {
return -1;
}
return x.1 + x!.1 + x!!.1 + x.1! + x!!.1!!;
}
@method_id(141)
fun test41() {
var t: (int, int)? = null;
return sameTensor(t = (1, 2));
}
@method_id(142)
fun test42() {
var t: (int?, (int?, (int, int)?)?) = (getNullableInt(), (1, (2, 3)));
t.1 = (3,null);
__expect_type(t.1, "(int?, (int,int)?)");
__expect_type(t, "(int?, (int?, (int,int)?)?)");
return (t, t.1);
}
@method_id(143)
fun test43() {
var t1: ((int, int), int?) = ((1, 2), 3);
var t2: ((int?, int?), (int?,int?)?) = ((null, null), (null, 5));
t2.0 = t1.0 = (10, 11);
t2.1 = t1.1 = null;
return (t1, t2);
}
@method_id(144)
fun test44() {
var t1: ((int, int), int?) = ((1, 2), 3);
var t2: ((int?, int?), (int?,int?)?) = ((null, null), (null, 5));
t1.0 = t2.0 = (10, 11);
t1.1 = t2.1 = null;
__expect_type(t1, "((int, int), int?)");
__expect_type(t2, "((int?,int?), (int?,int?)?)");
return (t1, t2);
}
@method_id(145)
fun test45() {
var t: (int?, (int?, (int, int)?)?) = (getNullableInt(), (1, (2, 3)));
var t2 = sameTensor2(t.1 = (3,null));
return (t, t2, t.1);
}
fun autoInfer46() {
var t1: int? = 3;
var t2: (int, int)? = (4, 5);
__expect_type(t1, "int");
__expect_type(t2, "(int, int)");
return (t1, t2); // proven to be not null, inferred (int, (int,int))
}
@method_id(146)
fun test46() {
var r46_1: (int, (int,int)) = autoInfer46();
var r46_2: (int, (int,int)?) = autoInfer46();
return (r46_1, r46_2);
}
@method_id(147)
fun test47() {
var t1: int? = 3;
var t2: (int, int)? = (4, 5);
t1 = t2 = null;
__expect_type(t1, "null");
__expect_type(t2, "null");
var result = (t1, t2); // proven to be always null, inferred (null, null), 2 slots on a stack
return (result, 100, result.1, 100, t2 as (int, int)?);
}
fun test48() {
var t1: int? = getNullableInt();
if (t1 != null) {
var (t1 redef, t2) = (10, 5);
return t1 + t2;
var t2 redef = getNullableInt()!;
return t1 + t2;
}
return -1;
}
fun test49(x: int?) {
while (x == null) {
x = getNullableInt();
}
__expect_type(x, "int");
return x + 1;
}
fun test50() {
var (x: int?, y: int?) = (1, 2);
do {
x = getNullableInt();
y = getNullableInt();
} while (x == null || y == null);
return x + y;
}
fun test51() {
while (true) { return; }
// test that no error "control reaches end of function"
}
fun test52() {
do { } while (true);
}
fun test53() {
var x1: int? = getNullableInt();
var x2: int? = 5;
var x3: int? = 5;
var x10: int? = null;
var x11: int? = 5;
var x12: int? = 5;
while (x1 != null) {
__expect_type(x1, "int"); // because condition
__expect_type(x2, "int?"); // because re-assigned
__expect_type(x3, "int?"); // because re-assigned
__expect_type(x10, "null");
__expect_type(x11, "int");
x1 = getNullableInt();
__expect_type(x1, "int?");
assignToNullableInt(mutate x2, 5);
x3.assignToNullableInt(5);
x11 = 10;
assignToInt(mutate x12, 5);
}
__expect_type(x1, "null");
__expect_type(x2, "int?");
__expect_type(x3, "int?");
}
fun test54() {
var x1: int? = null;
var x2: int? = 5;
var x3: int? = 5;
var x10: int? = null;
var x11: int? = 5;
var x12: int? = 5;
do {
__expect_type(x1, "int?"); // because re-assigned
__expect_type(x2, "int?"); // because re-assigned
__expect_type(x3, "int?"); // because re-assigned
__expect_type(x10, "null");
__expect_type(x11, "int");
x1 = getNullableInt();
__expect_type(x1, "int?");
assignToNullableInt(mutate x2, 5);
if (random()) { x3.assignToNullableInt(5); }
x11 = 10;
assignToInt(mutate x12, 5);
} while (x1 != null);
__expect_type(x1, "null");
__expect_type(x2, "int?");
__expect_type(x3, "int?");
}
fun eq55<T>(v: T) { return v; }
fun test55() {
var x: int? = 4;
while (true) {
// currently, generic functions are instantiated at the type inferring step
// in case of loops, type inferring is re-enterable
// first iteration: x is int, eq<int> instantiated
// second (final) iteration: x is int?, eq<int?> instantiated
// (checked via codegen)
eq55(x);
__expect_type(x, "int?"); // types are checked (unlike generics instantiated) after inferring
x = random() ? 1 : null;
}
__expect_type(x, "int?");
}
fun test56() {
var i: int? = null;
var (j: int?, k: int?) = (null, null);
__expect_type(i, "null");
__expect_type(k, "null");
i = getTwo();
[j, ((k))] = [getTwo(), ((getTwo()))];
__expect_type(i, "int?");
__expect_type(j, "int?");
__expect_type(k, "int?");
}
fun main(x: int?): int {
return x == null ? -1 : x;
}
/**
@testcase | 0 | 1 | 1
@testcase | 123 | | 7
@testcase | 124 | 4 | 6
@testcase | 124 | null | 15
@testcase | 130 | -1 | 20
@testcase | 130 | 0 | 10
@testcase | 132 | | 15
@testcase | 133 | | 10
@testcase | 139 | | 16
@testcase | 140 | 5 | 25
@testcase | 141 | | 1 2
@testcase | 142 | | 5 3 (null) (null) 0 -1 3 (null) (null) 0
@testcase | 143 | | 10 11 (null) 10 11 (null) (null) 0
@testcase | 144 | | 10 11 (null) 10 11 (null) (null) 0
@testcase | 145 | | 5 3 (null) (null) 0 -1 3 (null) (null) (null) (null) 0 3 (null) (null) 0
@testcase | 146 | | 3 4 5 3 4 5 -1
@testcase | 147 | | (null) (null) 100 (null) 100 (null) (null) 0
@stderr warning: type `int` is always not null
@stderr warning: unreachable code
@stderr var t2 redef = getNullableInt()!;
@fif_codegen eq55<int?> PROC:<{
@fif_codegen eq55<int> PROC:<{
*/