diff options
| author | gingerBill <bill@gingerbill.org> | 2022-02-05 14:45:59 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2022-02-05 14:45:59 +0000 |
| commit | a4308e7246a995c745b120debbb61be9e1f19a38 (patch) | |
| tree | 7cb09836ff59ef491387a22cb6b13cda2dbe52f2 /src | |
| parent | 3439139b1c763fe239967bd8c90d8ccbc1e0867f (diff) | |
Improve union variant assignment determination
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d90f93180..d6b454bf4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -673,6 +673,42 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type return 1; } } + + // TODO(bill): Determine which rule is a better on in practice + #if 1 + if (dst->Union.variants.count == 1) { + Type *vt = dst->Union.variants[0]; + i64 score = check_distance_between_types(c, operand, vt); + if (score >= 0) { + return score+2; + } + } + #else + // NOTE(bill): check to see you can assign to it with one of the variants? + i64 prev_lowest_score = -1; + i64 lowest_score = -1; + for_array(i, dst->Union.variants) { + Type *vt = dst->Union.variants[i]; + i64 score = check_distance_between_types(c, operand, vt); + if (score >= 0) { + if (lowest_score < 0) { + lowest_score = score; + } else { + if (prev_lowest_score < 0) { + prev_lowest_score = lowest_score; + } else { + prev_lowest_score = gb_min(prev_lowest_score, lowest_score); + } + lowest_score = gb_min(lowest_score, score); + } + } + } + if (lowest_score >= 0) { + if (prev_lowest_score != lowest_score) { // remove possible ambiguities + return lowest_score+2; + } + } + #endif } if (is_type_relative_pointer(dst)) { |