commit a2429ed9053bf5e78aa7dbd707abaf092f4252d4
parent 146eaad1d72119c443c934a97f8913584d172885
Author: Eyal Sawady <ecs@d2evs.net>
Date: Sat, 4 Sep 2021 07:17:09 +0000
result reduction: merge `type` with `const type`
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
2 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/src/type_store.c b/src/type_store.c
@@ -975,6 +975,7 @@ type_store_lookup_tuple(struct type_store *store, struct type_tuple *values)
// Algorithm:
// - Deduplicate and collect nested unions
// - Merge *type with nullable *type
+// - Merge type with const type
// - If one of the types is null:
// - If there's more than one pointer type, error out
// - If there's one pointer type, make it nullable and drop the null
@@ -1002,6 +1003,22 @@ type_store_reduce_result(struct type_store *store, struct type_tagged_union *in)
struct type_tagged_union *i = *tu;
bool dropped = false;
const struct type *it = i->type;
+
+ if (it->flags && TYPE_CONST) {
+ for (struct type_tagged_union **j = ∈ *j;
+ j = &(*j)->next) {
+ const struct type *jt = (*j)->type;
+ if (jt == it) {
+ continue;
+ }
+ jt = type_store_lookup_with_flags(store, jt,
+ jt->flags | TYPE_CONST);
+ if (jt == it) {
+ *j = (*j)->next;
+ }
+ }
+ }
+
for (struct type_tagged_union *j = in; j != i; j = j->next) {
const struct type *jt = j->type;
assert(it->id != jt->id);
diff --git a/tests/30-reduction.c b/tests/30-reduction.c
@@ -103,6 +103,16 @@ int main(void) {
test(&ctx, "(*int | const nullable *int)",
"if (true) null: *int "
"else null: const nullable *int");
+ test(&ctx, "const rune",
+ "if (true) 'a' "
+ "else 'a': const rune");
+ test(&ctx, "const rune",
+ "if (true) 'a': const rune "
+ "else 'a'");
+ test(&ctx, "(*int | const nullable *int)",
+ "if (true) null: *int "
+ "else if (true) null: const nullable *int "
+ "else null: nullable *int");
test(&ctx, "",
"if (true) null "