Compiler assert when using generic parameters list without any parameters. #2369

This commit is contained in:
Christoffer Lerno
2025-08-05 12:50:36 +02:00
parent 00b88a8027
commit aa910a1c44
10 changed files with 63 additions and 12 deletions

View File

@@ -16,6 +16,7 @@
- Fixed: regression in comments for `@deprecated` and `@pure`.
- Detect recursive creation of generics #2366.
- Compiler assertion when defining a function with return type untyped_list #2368.
- Compiler assert when using generic parameters list without any parameters. #2369
### Stdlib changes
- Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`.

View File

@@ -872,7 +872,7 @@ typedef struct
typedef struct
{
ExprId parent;
Expr **parmeters;
Expr **parameters;
} ExprGenericIdent;
typedef struct

View File

@@ -319,7 +319,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
return expr;
case EXPR_GENERIC_IDENT:
MACRO_COPY_EXPRID(expr->generic_ident_expr.parent);
MACRO_COPY_EXPR_LIST(expr->generic_ident_expr.parmeters);
MACRO_COPY_EXPR_LIST(expr->generic_ident_expr.parameters);
return expr;
case EXPR_MACRO_BODY_EXPANSION:
MACRO_COPY_EXPR_LIST(expr->body_expansion_expr.values);

View File

@@ -73,8 +73,29 @@ bool parse_range(ParseContext *c, Range *range)
range->end = 0;
return true;
}
bool parse_generic_expr_list(ParseContext *c, Expr ***exprs_ref)
{
SourceSpan start = c->span;
advance_and_verify(c, TOKEN_LBRACE);
if (try_consume(c, TOKEN_RBRACE))
{
print_error_at(extend_span_with_token(start, c->prev_span), "At least one generic parameter was expected here.");
return false;
}
do
{
ASSIGN_EXPR_OR_RET(Expr *expr, parse_expr(c), false);
vec_add(*exprs_ref, expr);
if (!try_consume(c, TOKEN_COMMA))
{
CONSUME_OR_RET(TOKEN_RBRACE, false);
return true;
}
} while (!try_consume(c, TOKEN_RBRACE));
return true;
}
bool parse_expr_list(ParseContext *c, Expr ***exprs_ref, TokenType end_token)
static bool parse_expr_list(ParseContext *c, Expr ***exprs_ref, TokenType end_token)
{
while (!try_consume(c, end_token))
{
@@ -1080,8 +1101,7 @@ static Expr *parse_generic_expr(ParseContext *c, Expr *left, SourceSpan lhs_star
ASSERT(left && expr_ok(left));
Expr *subs_expr = expr_new(EXPR_GENERIC_IDENT, lhs_start);
subs_expr->generic_ident_expr.parent = exprid(left);
advance_and_verify(c, TOKEN_LBRACE);
if (!parse_expr_list(c, &subs_expr->generic_ident_expr.parmeters, TOKEN_RBRACE)) return poisoned_expr;
if (!parse_generic_expr_list(c, &subs_expr->generic_ident_expr.parameters)) return poisoned_expr;
RANGE_EXTEND_PREV(subs_expr);
return subs_expr;
}

View File

@@ -499,8 +499,7 @@ static inline TypeInfo *parse_generic_type(ParseContext *c, TypeInfo *type)
{
ASSERT(type_info_ok(type));
TypeInfo *generic_type = type_info_new(TYPE_INFO_GENERIC, type->span);
advance_and_verify(c, TOKEN_LBRACE);
if (!parse_expr_list(c, &generic_type->generic.params, TOKEN_RBRACE)) return poisoned_type_info;
if (!parse_generic_expr_list(c, &generic_type->generic.params)) return poisoned_type_info;
generic_type->generic.base = type;
return generic_type;
}

View File

@@ -55,7 +55,7 @@ Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type);
Decl *parse_var_decl(ParseContext *c);
bool parse_current_is_expr(ParseContext *c);
bool parse_joined_strings(ParseContext *c, const char **str_ref, size_t *len_ref);
bool parse_expr_list(ParseContext *c, Expr ***exprs_ref, TokenType end_token);
bool parse_generic_expr_list(ParseContext *c, Expr ***exprs_ref);
bool parse_parameters(ParseContext *c, Decl ***params_ref,
Variadic *variadic, int *vararg_index_ref, ParameterParseKind parse_kind);

View File

@@ -5164,7 +5164,7 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con
ASSERT(parameter_count > 0);
if (parameter_count != vec_size(params))
{
ASSERT(vec_size(params));
ASSERT_AT(span, vec_size(params));
sema_error_at(c, extend_span_with_token(params[0]->span, vectail(params)->span),
"The generic module expected %d arguments, but you supplied %d, did you make a mistake?",
parameter_count,

View File

@@ -10073,7 +10073,7 @@ static inline bool sema_expr_analyse_generic_ident(SemaContext *context, Expr *e
}
Decl *symbol = sema_analyse_parameterized_identifier(context, parent->unresolved_ident_expr.path,
parent->unresolved_ident_expr.ident, parent->span,
expr->generic_ident_expr.parmeters, NULL);
expr->generic_ident_expr.parameters, NULL);
if (!decl_ok(symbol)) return false;
expr_resolve_ident(expr, symbol);
return true;

View File

@@ -0,0 +1,31 @@
module values {Type};
struct Values
{
Type[] values;
int count;
}
fn void test()
{
}
module main;
import values;
import std::collections::list;
fn void test1()
{
int x = values::test{}(); // #error: At least one generic parameter
}
fn void test2()
{
List{Values{ }} v1s; // #error: At least one generic parameter
}
fn void main()
{
List{Values{int}} v2s;
}

View File

@@ -1,10 +1,10 @@
struct Foo {
void bar; // #error: Members cannot be of
void bar; // #error: Members cannot
}
alias Void = void;
struct Foo2 {
Void bar; // #error: Members cannot be of
Void bar; // #error: Members cannot
}
typedef Void2 = void;