aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-05-14 00:00:10 +0100
committergingerBill <bill@gingerbill.org>2020-05-14 00:00:10 +0100
commitaf1d4d6e72eeb75b32c40f3d4ca7bf6a78e8a043 (patch)
treec56c070a4458fcf020e45294b3dde1d408d7fbec /src
parentf6c7a0c9b8086f43f958f69b2ad3e960e408bc57 (diff)
Implement Allow `.?` operator to unwrap any union #549
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp21
-rw-r--r--src/parser.hpp2
2 files changed, 21 insertions, 2 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index f6fbd25c4..d55692a41 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -8897,12 +8897,31 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (ta->type != nullptr && ta->type->kind == Ast_UnaryExpr && ta->type->UnaryExpr.op.kind == Token_Question) {
if (!is_type_union(src)) {
gbString str = type_to_string(o->type);
- error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %s", str);
+ error(o->expr, "Type assertions with .? can only operate on unions, got %s", str);
gb_string_free(str);
o->mode = Addressing_Invalid;
o->expr = node;
return kind;
}
+
+ if (bsrc->Union.variants.count != 1 && type_hint != nullptr) {
+ bool allowed = false;
+ for_array(i, bsrc->Union.variants) {
+ Type *vt = bsrc->Union.variants[i];
+ if (are_types_identical(vt, type_hint)) {
+ allowed = true;
+ add_type_info_type(c, vt);
+ break;
+ }
+ }
+ if (allowed) {
+ add_type_info_type(c, o->type);
+ o->type = type_hint;
+ o->mode = Addressing_OptionalOk;
+ return kind;
+ }
+ }
+
if (bsrc->Union.variants.count != 1) {
error(o->expr, "Type assertions with .? can only operate on unions with 1 variant, got %lld", cast(long long)bsrc->Union.variants.count);
o->mode = Addressing_Invalid;
diff --git a/src/parser.hpp b/src/parser.hpp
index ca480f403..61be8c54a 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -292,7 +292,7 @@ AST_KIND(_ExprBegin, "", bool) \
AST_KIND(TernaryExpr, "ternary expression", struct { Ast *cond, *x, *y; }) \
AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \
AST_KIND(TernaryWhenExpr, "ternary when expression", struct { Ast *x, *cond, *y; }) \
- AST_KIND(TypeAssertion, "type assertion", struct { Ast *expr; Token dot; Ast *type; }) \
+ AST_KIND(TypeAssertion, "type assertion", struct { Ast *expr; Token dot; Ast *type; Type *type_hint; }) \
AST_KIND(TypeCast, "type cast", struct { Token token; Ast *type, *expr; }) \
AST_KIND(AutoCast, "auto_cast", struct { Token token; Ast *expr; }) \
AST_KIND(_ExprEnd, "", bool) \