commit 533ba755deb3a724908edcbd2dd01af2c86e6654
parent 3017c9c4f12e11c392c9c7bc3d0cf70ca1b3440e
Author: Ajay R <ar324@protonmail.com>
Date: Thu, 10 Mar 2022 10:03:43 +0000
types: disallow assignment of non-void types and error types to void
Signed-off-by: Ajay R <ar324@protonmail.com>
Diffstat:
2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/src/types.c b/src/types.c
@@ -719,7 +719,7 @@ type_is_assignable(const struct type *to, const struct type *from)
struct type _to, _from;
const struct type *to_orig = to, *from_orig = from;
to = strip_flags(to, &_to), from = strip_flags(from, &_from);
- if (to->id == from->id) {
+ if (to->id == from->id && to->storage != STORAGE_VOID) {
return true;
}
@@ -799,7 +799,8 @@ type_is_assignable(const struct type *to, const struct type *from)
case STORAGE_STRING:
return to->id == builtin_type_ptr_const_char.id;
case STORAGE_VOID:
- return true;
+ return to_orig->id == from_orig->id &&
+ (from_orig->flags & TYPE_ERROR) == (to_orig->flags & TYPE_ERROR);
case STORAGE_SLICE:
if (from->storage == STORAGE_POINTER) {
from = type_dealias(from->pointer.referent);
diff --git a/tests/23-errors.ha b/tests/23-errors.ha
@@ -38,8 +38,33 @@ export fn main() int = {
err_if_false(true)!;
};
+fn void_assignability() void = {
+ assert(rt::compile(`type err = !void;
+
+fn reterr() (int | err) = {
+ return err;
+};
+
+fn properr() void = {
+ reterr()?;
+};
+
+export fn main() void = void;`) != 0); // error types cannot be assigned to void
+
+ assert(rt::compile(`fn disallow_1() void = {
+ return "I am illegal";
+};
+
+fn disallow_2() void = {
+ return 12;
+};
+
+export fn main() void = void;`) != 0); // non-void types cannot be assigned to void
+};
+
export fn main() void = {
assignability();
propagate();
cannotignore();
+ void_assignability();
};