aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-07-29 14:23:34 +0100
committerGinger Bill <bill@gingerbill.org>2017-07-29 14:23:34 +0100
commit7bd62481ad879704d68104dae5fea759074eb570 (patch)
tree7a26cf78357ab1c6f7b0b63171ab025a41100223 /src
parentfbd27d7c459bab630af56ba0bf608f9d51109a07 (diff)
Fix `nil` assignment to unions
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp136
1 files changed, 65 insertions, 71 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 106f1e9c7..0b5ea9e43 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -4362,99 +4362,93 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
} break;
case Type_Union:
- {
- gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
- defer (gb_temp_arena_memory_end(tmp));
- isize count = t->Union.variants.count;
- i64 *scores = gb_alloc_array(c->tmp_allocator, i64, count);
- i32 success_count = 0;
- i32 first_success_index = -1;
- for_array(i, t->Union.variants) {
- Type *vt = t->Union.variants[i];
- i64 score = 0;
- if (check_is_assignable_to_with_score(c, operand, vt, &score)) {
- scores[i] = score;
- success_count += 1;
- if (first_success_index < 0) {
- first_success_index = i;
+ if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
+ gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
+ defer (gb_temp_arena_memory_end(tmp));
+ isize count = t->Union.variants.count;
+ i64 *scores = gb_alloc_array(c->tmp_allocator, i64, count);
+ i32 success_count = 0;
+ i32 first_success_index = -1;
+ for_array(i, t->Union.variants) {
+ Type *vt = t->Union.variants[i];
+ i64 score = 0;
+ if (check_is_assignable_to_with_score(c, operand, vt, &score)) {
+ scores[i] = score;
+ success_count += 1;
+ if (first_success_index < 0) {
+ first_success_index = i;
+ }
}
}
- }
-
- gbString type_str = type_to_string(target_type);
- defer (gb_string_free(type_str));
- if (success_count == 1) {
- operand->mode = Addressing_Value;
- operand->type = t->Union.variants[first_success_index];
- target_type = t->Union.variants[first_success_index];
- break;
- } else if (success_count > 1) {
- GB_ASSERT(first_success_index >= 0);
- operand->mode = Addressing_Invalid;
- convert_untyped_error(c, operand, target_type);
+ gbString type_str = type_to_string(target_type);
+ defer (gb_string_free(type_str));
- gb_printf_err("Ambiguous type conversion to `%s`, which variant did you mean:\n\t", type_str);
- i32 j = 0;
- for (i32 i = first_success_index; i < count; i++) {
- if (scores[i] == 0) continue;
- if (j > 0 && success_count > 2) gb_printf_err(", ");
- if (j == success_count-1) {
- if (success_count == 2) {
- gb_printf_err(" or ");
- } else {
- gb_printf_err(" or ");
+ if (success_count == 1) {
+ operand->mode = Addressing_Value;
+ operand->type = t->Union.variants[first_success_index];
+ target_type = t->Union.variants[first_success_index];
+ break;
+ } else if (success_count > 1) {
+ GB_ASSERT(first_success_index >= 0);
+ operand->mode = Addressing_Invalid;
+ convert_untyped_error(c, operand, target_type);
+
+ gb_printf_err("Ambiguous type conversion to `%s`, which variant did you mean:\n\t", type_str);
+ i32 j = 0;
+ for (i32 i = first_success_index; i < count; i++) {
+ if (scores[i] == 0) continue;
+ if (j > 0 && success_count > 2) gb_printf_err(", ");
+ if (j == success_count-1) {
+ if (success_count == 2) gb_printf_err(" ");
+ gb_printf_err("or ");
}
+ gbString str = type_to_string(t->Union.variants[i]);
+ gb_printf_err("`%s`", str);
+ gb_string_free(str);
+ j++;
}
- gbString str = type_to_string(t->Union.variants[i]);
- gb_printf_err("`%s`", str);
- gb_string_free(str);
- j++;
- }
- gb_printf_err("\n\n");
+ gb_printf_err("\n\n");
- return;
- } else if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
- target_type = t_untyped_undef;
- } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
- operand->mode = Addressing_Invalid;
- convert_untyped_error(c, operand, target_type);
- if (count > 0) {
- gb_printf_err("`%s` is a union which only excepts the following types:\n", type_str);
- gb_printf_err("\t");
- for (i32 i = 0; i < count; i++) {
- Type *v = t->Union.variants[i];
- if (i > 0 && count > 2) gb_printf_err(", ");
- if (i == count-1) {
- if (count == 2) {
- gb_printf_err(" or ");
- } else {
+ return;
+ } else if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
+ target_type = t_untyped_undef;
+ } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
+ operand->mode = Addressing_Invalid;
+ convert_untyped_error(c, operand, target_type);
+ if (count > 0) {
+ gb_printf_err("`%s` is a union which only excepts the following types:\n", type_str);
+ gb_printf_err("\t");
+ for (i32 i = 0; i < count; i++) {
+ Type *v = t->Union.variants[i];
+ if (i > 0 && count > 2) gb_printf_err(", ");
+ if (i == count-1) {
+ if (count == 2) gb_printf_err(" ");
gb_printf_err("or ");
}
+ gbString str = type_to_string(v);
+ gb_printf_err("`%s`", str);
+ gb_string_free(str);
}
- gbString str = type_to_string(v);
- gb_printf_err("`%s`", str);
- gb_string_free(str);
- }
- gb_printf_err("\n\n");
+ gb_printf_err("\n\n");
+ }
+ return;
}
- return;
}
-
- }
- /* fallthrough */
+ /* fallthrough */
default:
if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
target_type = t_untyped_undef;
- } else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
+ } else if (is_type_untyped_nil(operand->type) && type_has_nil(target_type)) {
+ target_type = t_untyped_nil;
+ } else {
operand->mode = Addressing_Invalid;
convert_untyped_error(c, operand, target_type);
return;
}
- target_type = t_untyped_nil;
break;
}