Allow implicit selectors to unions with only one enum variant

This commit is contained in:
gingerBill
2019-03-24 12:14:45 +00:00
parent b1684fe455
commit a137a06b00
+36 -12
View File
@@ -6430,34 +6430,58 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->expr = node; o->expr = node;
o->mode = Addressing_Invalid; o->mode = Addressing_Invalid;
if (type_hint == nullptr) { Type *th = type_hint;
if (th == nullptr) {
gbString str = expr_to_string(node); gbString str = expr_to_string(node);
error(node, "Cannot determine type for implicit selector expression '%s'", str); error(node, "Cannot determine type for implicit selector expression '%s'", str);
gb_string_free(str); gb_string_free(str);
return Expr_Expr; return Expr_Expr;
} }
o->type = type_hint; o->type = th;
if (!is_type_enum(type_hint)) { Type *enum_type = th;
gbString typ = type_to_string(type_hint);
gbString str = expr_to_string(node); if (!is_type_enum(th)) {
error(node, "Invalid type '%s' for implicit selector expression '%s'", typ, str); bool show_error = true;
gb_string_free(str); if (is_type_union(th)) {
gb_string_free(typ); Type *union_type = base_type(th);
return Expr_Expr; isize enum_count = 0;
Type *et = nullptr;
for_array(i, union_type->Union.variants) {
Type *vt = union_type->Union.variants[i];
if (is_type_enum(vt)) {
enum_count += 1;
et = vt;
}
}
if (enum_count == 1) {
show_error = false;
enum_type = et;
}
}
if (show_error) {
gbString typ = type_to_string(th);
gbString str = expr_to_string(node);
error(node, "Invalid type '%s' for implicit selector expression '%s'", typ, str);
gb_string_free(str);
gb_string_free(typ);
return Expr_Expr;
}
} }
GB_ASSERT(ise->selector->kind == Ast_Ident); GB_ASSERT(ise->selector->kind == Ast_Ident);
String name = ise->selector->Ident.token.string; String name = ise->selector->Ident.token.string;
Type *enum_type = base_type(type_hint); enum_type = base_type(enum_type);
GB_ASSERT(enum_type->kind == Type_Enum); GB_ASSERT(enum_type->kind == Type_Enum);
Entity *e = scope_lookup_current(enum_type->Enum.scope, name); Entity *e = scope_lookup_current(enum_type->Enum.scope, name);
if (e == nullptr) { if (e == nullptr) {
gbString typ = type_to_string(type_hint); gbString typ = type_to_string(th);
error(node, "Undeclared name %.*s for type '%s'", LIT(name), typ); error(node, "Undeclared name %.*s for type '%s'", LIT(name), typ);
gb_string_free(typ); gb_string_free(typ);
return Expr_Expr; return Expr_Expr;
} }
GB_ASSERT(are_types_identical(base_type(e->type), base_type(type_hint))); GB_ASSERT(are_types_identical(base_type(e->type), enum_type));
GB_ASSERT(e->kind == Entity_Constant); GB_ASSERT(e->kind == Entity_Constant);
o->value = e->Constant.value; o->value = e->Constant.value;
o->mode = Addressing_Constant; o->mode = Addressing_Constant;