// 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(v: T) { return v; } fun getTwo(): 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(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(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(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 instantiated // second (final) iteration: x is int?, eq 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 PROC:<{ @fif_codegen eq55 PROC:<{ */