aboutsummaryrefslogtreecommitdiff
path: root/types.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-12-11 13:25:00 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-12-11 13:25:00 -0500
commit7e9a976fe52bdce8e7e69335b85514bc48549f70 (patch)
treeb7e5bba47e7ae745c13302b3e962d1602e4f0ffb /types.c
parent6c5c75961957db64e0074864ce0d3b7357f5a03a (diff)
Optional promotion in comparisons
Diffstat (limited to 'types.c')
-rw-r--r--types.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/types.c b/types.c
index 189cec89..966698ad 100644
--- a/types.c
+++ b/types.c
@@ -325,6 +325,9 @@ PUREFUNC const char *enum_single_value_tag(type_t *enum_type, type_t *t)
PUREFUNC bool can_promote(type_t *actual, type_t *needed)
{
+ if (!actual || !needed)
+ return false;
+
// No promotion necessary:
if (type_eq(actual, needed))
return true;
@@ -354,13 +357,19 @@ PUREFUNC bool can_promote(type_t *actual, type_t *needed)
if (actual->tag == PointerType && can_promote(Match(actual, PointerType)->pointed, needed))
return true;
- // Optional num -> num
- if (needed->tag == NumType && actual->tag == OptionalType && Match(actual, OptionalType)->type->tag == NumType)
- return can_promote(Match(actual, OptionalType)->type, needed);
+ if (actual->tag == OptionalType) {
+ // Ambiguous `none` to concrete optional
+ if (Match(actual, OptionalType)->type == NULL)
+ return (needed->tag == OptionalType);
- // Optional promotion:
- if (needed->tag == OptionalType && can_promote(actual, Match(needed, OptionalType)->type))
- return true;
+ // Optional num -> num
+ if (needed->tag == NumType && actual->tag == OptionalType && Match(actual, OptionalType)->type->tag == NumType)
+ return can_promote(Match(actual, OptionalType)->type, needed);
+
+ // Optional promotion:
+ if (needed->tag == OptionalType && Match(needed, OptionalType)->type != NULL && can_promote(actual, Match(needed, OptionalType)->type))
+ return true;
+ }
if (needed->tag == PointerType && actual->tag == PointerType) {
auto needed_ptr = Match(needed, PointerType);