aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-02-05 14:45:59 +0000
committergingerBill <bill@gingerbill.org>2022-02-05 14:45:59 +0000
commita4308e7246a995c745b120debbb61be9e1f19a38 (patch)
tree7cb09836ff59ef491387a22cb6b13cda2dbe52f2 /src
parent3439139b1c763fe239967bd8c90d8ccbc1e0867f (diff)
Improve union variant assignment determination
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp36
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)) {