Browse Source

Allow implicit selectors to unions with only one enum variant

gingerBill 6 years ago
parent
commit
a137a06b00
1 changed files with 36 additions and 12 deletions
  1. 36 12
      src/check_expr.cpp

+ 36 - 12
src/check_expr.cpp

@@ -6430,34 +6430,58 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		o->expr = node;
 		o->mode = Addressing_Invalid;
 
-		if (type_hint == nullptr) {
+		Type *th = type_hint;
+
+		if (th == nullptr) {
 			gbString str = expr_to_string(node);
 			error(node, "Cannot determine type for implicit selector expression '%s'", str);
 			gb_string_free(str);
 			return Expr_Expr;
 		}
-		o->type = type_hint;
-		if (!is_type_enum(type_hint)) {
-			gbString typ = type_to_string(type_hint);
-			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;
+		o->type = th;
+		Type *enum_type = th;
+
+		if (!is_type_enum(th)) {
+			bool show_error = true;
+			if (is_type_union(th)) {
+				Type *union_type = base_type(th);
+				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);
 		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);
 		Entity *e = scope_lookup_current(enum_type->Enum.scope, name);
 		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);
 			gb_string_free(typ);
 			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);
 		o->value = e->Constant.value;
 		o->mode = Addressing_Constant;