harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit a22f0c06a22868578215b1dc2897e297a5ee9121
parent 29cf8b8cf49e268392c15caed5f48ce0b71c8a39
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue,  5 Oct 2021 21:15:40 +0000

Fix type reduction

There were three issues, all of which were exposed by STORAGE_NULL's
value being changed in 1a0162835046c8030c80164e6be032332be1d0c9. The
first was that we were using `break` rather than `continue` when we
found a non-matching type while looking for nullable/non-nullable
pointers to consolidate. The change caused null to sort before `*int`
and `nullable *int`, causing this minimal reproduction to fail:

export fn main() void = {
	let x = match (0u8: (u8 | u16 | u32)) {
	case u8 =>
		yield null: *int;
	case u16 =>
		yield null: nullable *int;
	case u32 =>
		yield null;
	};
};

In addition to this, due to an incorrect usage of `&&` rather than `&`,
the const consolidation code was being run, exposing a bug in the linked
list traversal code causing a segfault.

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Msrc/type_store.c | 15+++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/type_store.c b/src/type_store.c @@ -1025,17 +1025,20 @@ type_store_reduce_result(struct type_store *store, struct type_tagged_union *in) bool dropped = false; const struct type *it = i->type; - if (it->flags && TYPE_CONST) { - for (struct type_tagged_union **j = &in; *j; - j = &(*j)->next) { + if (it->flags & TYPE_CONST) { + struct type_tagged_union **j = &in; + while (*j) { const struct type *jt = (*j)->type; if (jt == it) { + j = &(*j)->next; continue; } jt = type_store_lookup_with_flags(store, jt, jt->flags | TYPE_CONST); if (jt == it) { *j = (*j)->next; + } else { + j = &(*j)->next; } } } @@ -1045,13 +1048,13 @@ type_store_reduce_result(struct type_store *store, struct type_tagged_union *in) assert(it->id != jt->id); if (it->storage != STORAGE_POINTER || jt->storage != STORAGE_POINTER) { - break; + continue; } if (it->pointer.referent->id != jt->pointer.referent->id) { - break; + continue; } if (it->flags != jt->flags) { - break; + continue; } if ((it->pointer.flags & PTR_NULLABLE) || (jt->pointer.flags & PTR_NULLABLE)) {