It was checking if the source is an integer, not the destination. This
made it so all integer-based enums could be cast to any type.
Also, rune enums weren't handled here at all.
Reported at: https://lists.sr.ht/~sircmpwn/hare-users/%3Cd65c8dccf8f704e9fa5bf41cbca9e3dc@disroot.org%3E
Signed-off-by: Alexey Yerin <yyp@disroot.org>
---
v1 -> v2: actually fix castability
src/types.c | 5 ++++-
tests/15-enums.ha | 8 ++++++++
tests/26-regression.ha | 2 ++
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/types.c b/src/types.c
index 154acc7..9f58e62 100644
--- a/src/types.c
+++ b/src/types.c
@@ -1052,7 +1052,10 @@ type_is_castable(struct context *ctx, const struct type *to, const struct type *
return type_is_integer(ctx, to)
? to_orig : NULL;
case STORAGE_ENUM:
- return to->storage == STORAGE_ENUM || type_is_integer(ctx, from)
+ if (from->alias.type->storage == STORAGE_RUNE) {
+ return to->storage == STORAGE_RUNE ? to_orig : NULL;
+ }
+ return to->storage == STORAGE_ENUM || type_is_integer(ctx, to)
? to_orig : NULL;
case STORAGE_F32:
case STORAGE_F64:
diff --git a/tests/15-enums.ha b/tests/15-enums.ha
index 78482e6..ed557d5 100644
--- a/tests/15-enums.ha
+++ b/tests/15-enums.ha
@@ -65,6 +65,13 @@ fn storage() void = {
assert(rune_storage::FOO == '0' && rune_storage::BAR == '1');
};
+fn runes() void = {
+ let val = '1': rune_storage;
+ let val = rune_storage::FOO: rune;
+
+ compile(status::CHECK, "type a = enum rune { A = 'x' }; fn f() void = { a::A: str; };")!;
+};
+
fn reject() void = {
// enum type definition used outside type declaration
compile(status::PARSE, "export let a: enum { A, B } = 0;")!;
@@ -175,6 +182,7 @@ export fn main() void = {
implicit();
explicit();
storage();
+ runes();
reject();
interdependent();
aliases();
diff --git a/tests/26-regression.ha b/tests/26-regression.ha
index 1c8c074..b64f5fd 100644
--- a/tests/26-regression.ha
+++ b/tests/26-regression.ha
@@ -248,4 +248,6 @@ export fn main() void = {
// as three separate tokens, rather than as a float literal
assert(((1, 2), 3). // don't remove this comment
0.0 == 1);
+
+ compile(status::CHECK, "type e = enum { A }; fn f() void = { e::A: bool; };")!;
};
--
2.46.0