Skip to content

Commit

Permalink
Add contracts on @catch / @ok. Taking the $typeof of a wildcard optio…
Browse files Browse the repository at this point in the history
…nal returns `void!`
  • Loading branch information
lerno committed Nov 5, 2024
1 parent 7417072 commit 08d1b29
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 7 deletions.
11 changes: 11 additions & 0 deletions lib/std/core/builtin.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/sema_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion test/test_suite/cast/cast_to_failable.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
17 changes: 11 additions & 6 deletions test/test_suite/errors/optional_sizeof.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

0 comments on commit 08d1b29

Please sign in to comment.