From 08d1b29301eb057494a5b6c59278200f0db33ad4 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 5 Nov 2024 10:50:38 +0100 Subject: [PATCH] Add contracts on @catch / @ok. Taking the $typeof of a wildcard optional returns `void!` --- lib/std/core/builtin.c3 | 11 +++++++++++ releasenotes.md | 1 + src/compiler/sema_types.c | 5 +++++ test/test_suite/cast/cast_to_failable.c3 | 2 +- test/test_suite/errors/optional_sizeof.c3 | 17 +++++++++++------ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index d534e47fd..ccbd5f79d 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -324,13 +324,24 @@ macro swizzle2(v, v2, ...) @builtin { return $$swizzle2(v, v2, $vasplat); } +<* + Return the excuse in the Optional if it is Empty, otherwise + return a null fault. + @require @typekind(#expr) == OPTIONAL : `@catch expects an Optional value` +*> macro anyfault @catch(#expr) @builtin { if (catch f = #expr) return f; return anyfault {}; } +<* + Check if an Optional expression holds a value or is empty, returning true + if it has a value. + + @require @typekind(#expr) == OPTIONAL : `@ok expects an Optional value` +*> macro bool @ok(#expr) @builtin { if (catch #expr) return false; diff --git a/releasenotes.md b/releasenotes.md index 77a7215fe..1db95743a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -57,6 +57,7 @@ - Fixes with error handling recursive `@tag` #1583. - Sometimes generating introspection info would not be in the global scope causing a crash #1586. - @tag on macros cannot be retrieved with tagof #1582 +- Taking the $typeof of a wildcard optional returns `void!`. ### Stdlib changes - Remove unintended print of `char[]` as String diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 5c21de70a..7fcc15ad4 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -325,6 +325,11 @@ INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info) type_info->type = expr_type; return true; case STORAGE_WILDCARD: + if (expr_type->type_kind == TYPE_OPTIONAL) + { + type_info->type = type_get_optional(type_void); + return true; + } RETURN_SEMA_ERROR(expr, "This %sexpression lacks a concrete type.", type_is_optional(expr_type) ? "optional " : ""); case STORAGE_COMPILE_TIME: RETURN_SEMA_ERROR(expr, "This expression has a compile time type %s.", type_quoted_error_string(expr_type)); diff --git a/test/test_suite/cast/cast_to_failable.c3 b/test/test_suite/cast/cast_to_failable.c3 index 56d55b472..0625d48c4 100644 --- a/test/test_suite/cast/cast_to_failable.c3 +++ b/test/test_suite/cast/cast_to_failable.c3 @@ -7,7 +7,7 @@ fn void test() { int! x; double! y; - int! d = ($typeof(MyErr.FOO?))(x); // #error: optional expression lacks a concrete + int! d = ($typeof(MyErr.FOO?))(x); // #error: Casting to an optional int! df = ($typeof(y))(x); // #error: Casting to an optional type is not allowed double! df2 = ($typeof(y!!))(x); } diff --git a/test/test_suite/errors/optional_sizeof.c3 b/test/test_suite/errors/optional_sizeof.c3 index 1ad8ae019..e8455b594 100644 --- a/test/test_suite/errors/optional_sizeof.c3 +++ b/test/test_suite/errors/optional_sizeof.c3 @@ -3,36 +3,41 @@ fn int! abc() return 1; } macro test() +{ + return @catch(abc())?!!; +} + +macro test2() { return @catch(abc())?; } fn void a() { - String s = $typeof(test()).qnameof; // #error: This optional expression lacks + String s = $typeof(test()).qnameof; // #error: This expression lacks } fn void b() { - $sizeof(test()); // #error: This optional expression lacks + $sizeof(test()); // #error: This expression lacks } fn void c() { - $sizeof(test() ?? 1); + $sizeof(test2() ?? 1); } fn void! d() { - $typeof(test()!) g; // #error: This expression lacks a concrete type + $typeof(test2()!) g; // #error: This expression lacks a concrete type } macro e() { - var g = test()!; // #error: No type can be inferred from the optional result + var g = test2()!; // #error: No type can be inferred from the optional result } fn void! h() { e(); -} \ No newline at end of file +}