Skip to content

Commit 6354018

Browse files
committed
[Tolk] Better handle nested unknown types at assignment
Fix an issue with a ternary operator that returns (and is assigned to) multiple variables
1 parent d9bb6bb commit 6354018

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

tolk-tester/tests/dicts-demo.tolk

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ fun test104() {
9393
);
9494
}
9595

96+
@method_id(105)
97+
fun test105(takeNext: bool) {
98+
var dict = createEmptyDict();
99+
dict.uDictSet(32, 0, stringHexToSlice("01"));
100+
dict.uDictSet(32, 8, stringHexToSlice("02"));
101+
var (next, data, found) = takeNext ? dict.uDictGetNext(32, -1) : dict.uDictGetPrev(32, 9);
102+
__expect_type(found, "bool");
103+
assert(found, 10);
104+
return data!.loadUint(8);
105+
}
106+
96107
fun main() {}
97108

98109
/**
@@ -102,4 +113,6 @@ fun main() {}
102113
@testcase | 102 | | [ [ 4 104 ] [ 3 103 ] [ 2 102 ] [ 1 101 ] ]
103114
@testcase | 103 | | 1 1 2 1 3 (null)
104115
@testcase | 104 | | 12 34 56 78 0
116+
@testcase | 105 | -1 | 1
117+
@testcase | 105 | 0 | 2
105118
*/

tolk/smart-casts-cfg.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,22 @@ static TypePtr calculate_type_lca(TypePtr a, TypePtr b, bool* became_union = nul
218218
return resulting_union;
219219
}
220220

221+
// when `var v = rhs`, `v` is `unknown` before assignment (before rhs->inferred_type is assigned to it);
222+
// when `var (v1,v2,v3) = rhs`, left side is `(unknown,unknown,unknown)`
223+
static bool is_type_unknown_from_var_lhs_decl(TypePtr t) {
224+
if (t == TypeDataUnknown::create()) {
225+
return true;
226+
}
227+
if (const auto* t_tensor = t->try_as<TypeDataTensor>()) {
228+
bool all_unknown = true;
229+
for (TypePtr item : t_tensor->items) {
230+
all_unknown &=is_type_unknown_from_var_lhs_decl(item);
231+
}
232+
return all_unknown;
233+
}
234+
return false;
235+
}
236+
221237
// merge (unify) of two sign states: what sign do we definitely have
222238
// it's used on data flow rejoin
223239
// example: `if (x > 0) ... else ...`; lca(Positive, NonPositive) = Unknown
@@ -263,7 +279,7 @@ BoolState calculate_bool_lca(BoolState a, BoolState b) {
263279
void TypeInferringUnifyStrategy::unify_with(TypePtr next, TypePtr dest_hint) {
264280
// example: `var r = ... ? int8 : int16`, will be inferred as `int8 | int16` (via unification)
265281
// but `var r: int = ... ? int8 : int16`, will be inferred as `int` (it's dest_hint)
266-
if (dest_hint && dest_hint != TypeDataUnknown::create() && !dest_hint->unwrap_alias()->try_as<TypeDataUnion>()) {
282+
if (dest_hint && !is_type_unknown_from_var_lhs_decl(dest_hint) && !dest_hint->unwrap_alias()->try_as<TypeDataUnion>()) {
267283
if (dest_hint->can_rhs_be_assigned(next)) {
268284
next = dest_hint;
269285
}

0 commit comments

Comments
 (0)