Fix requirement to use prefix when using $defined

This commit is contained in:
Christoffer Lerno
2025-12-13 00:38:19 +01:00
parent a0ab10c23e
commit 0c0d0ace4d
3 changed files with 33 additions and 11 deletions

View File

@@ -78,7 +78,7 @@ enum Month : char (String name, String abbrev, int days, bool leap)
fn Time now()
{
$if $defined(native_timestamp):
$if $defined(os::native_timestamp):
return os::native_timestamp();
$else
return (Time)0;

View File

@@ -17,6 +17,8 @@
- Compiler crash when concatenating structs and arrays to an untyped list.
- Strings assigned to longer arrays would crash codegen, e.g. `char[10] x = "abcd`.
- Typedefs and structs with inline types supporting lengthof would not work with lengthof #2641.
- `$defined(foo())` now correctly errors if `foo()` would require a path.
- `@if($defined((char*){}.foo()))` does not error if `foo` is missing.
### Stdlib changes
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.

View File

@@ -50,7 +50,7 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr
static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error);
static inline bool sema_expr_analyse_binary(SemaContext *context, Type *infer_type, Expr *expr, bool *failed_ref);
static inline bool sema_expr_resolve_ct_eval(SemaContext *context, Expr *expr);
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr);
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr, bool *failed_ref);
static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr);
static inline bool sema_expr_analyse_ternary(SemaContext *context, Type *infer_type, Expr *expr);
@@ -1197,7 +1197,7 @@ static inline bool sema_identifier_find_possible_inferred(SemaContext *context,
}
}
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr)
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr, bool *failed_ref)
{
ASSERT(expr);
ASSERT_SPAN(expr, expr->unresolved_ident_expr.ident);
@@ -1231,6 +1231,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
// Rerun if we can't do inference.
if (!decl)
{
if (failed_ref) return *failed_ref = true, false;
if (!expr->unresolved_ident_expr.path && expr->unresolved_ident_expr.is_const && (!to || to->canonical->type_kind != TYPE_ENUM))
{
CompilationUnit **units = context->unit->module->units;
@@ -1256,6 +1257,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
ASSERT_SPAN(expr, !decl);
return false;
}
if (failed_ref && decl_is_defaulted_var(decl)) return *failed_ref = true, false;
if (decl_needs_prefix(decl))
{
@@ -3727,10 +3729,28 @@ static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr
expr->type = decl->type;
return true;
}
static inline bool sema_expr_analyse_call_expr_dispatch(SemaContext *context, Expr *expr, bool *no_match_ref)
{
switch (expr->expr_kind)
{
case EXPR_UNRESOLVED_IDENTIFIER:
return sema_expr_analyse_identifier(context, NULL, expr, no_match_ref);
case EXPR_ACCESS_UNRESOLVED:
return sema_expr_analyse_access(context, expr, no_match_ref);
default:
return sema_analyse_expr_dispatch(context, expr);
}
}
static inline bool sema_expr_analyse_call_expr(SemaContext *context, Expr *expr, bool *no_match_ref)
{
RESOLVE(expr, sema_expr_analyse_call_expr_dispatch(context, expr, no_match_ref));
}
static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool *no_match_ref)
{
Expr *func_expr = exprptr(expr->call_expr.function);
if (!sema_analyse_expr(context, func_expr)) return false;
if (!sema_expr_analyse_call_expr(context, func_expr, no_match_ref)) return false;
bool optional = func_expr->type && IS_OPTIONAL(func_expr);
Decl *decl;
Expr *struct_var = NULL;
@@ -10966,12 +10986,12 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
}
break;
case EXPR_UNRESOLVED_IDENTIFIER:
{
Decl *decl = sema_find_path_symbol(active_context, main_expr->unresolved_ident_expr.ident, main_expr->unresolved_ident_expr.path);
if (!decl_ok(decl)) goto FAIL;
success = decl != NULL && !decl_is_defaulted_var(decl);
if (!sema_expr_analyse_identifier(active_context, NULL, main_expr, &failed))
{
if (!failed) goto FAIL;
success = false;
}
break;
}
case EXPR_HASH_IDENT:
{
if (unroll_hash)
@@ -11750,7 +11770,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
case EXPR_IDENTIFIER:
UNREACHABLE
case EXPR_UNRESOLVED_IDENTIFIER:
return sema_expr_analyse_identifier(context, NULL, expr);
return sema_expr_analyse_identifier(context, NULL, expr, NULL);
case EXPR_CALL:
return sema_expr_analyse_call(context, expr, NULL);
case EXPR_SUBSCRIPT:
@@ -12397,7 +12417,7 @@ RETRY:
if (!sema_expr_analyse_initializer_list(context, to, expr, no_match_ref)) return expr_poison(expr);
break;
case EXPR_UNRESOLVED_IDENTIFIER:
if (!sema_expr_analyse_identifier(context, to, expr)) return expr_poison(expr);
if (!sema_expr_analyse_identifier(context, to, expr, NULL)) return expr_poison(expr);
break;
case EXPR_LAMBDA:
if (!sema_expr_analyse_lambda(context, to, expr)) return expr_poison(expr);