aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2026-01-15 18:03:09 +0000
committerGitHub <noreply@github.com>2026-01-15 18:03:09 +0000
commitfaacac33ab6c03266e2c1407f027be811e97e093 (patch)
tree48b83381b47c4ae73dd5e87d1a3c71629cf176e9 /src/check_expr.cpp
parent7f509c01f1c912e2d4ccf5d8f1a029167fff107e (diff)
parent59ae82634ed69b019a8965d1120dd8c7c5a7a605 (diff)
Merge pull request #6135 from odin-lang/bill/must-tail
`#must_tail`
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp33
1 files changed, 30 insertions, 3 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index cd2307c6d..74ae02f94 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -8210,7 +8210,7 @@ gb_internal void check_objc_call_expr(CheckerContext *c, Operand *operand, Ast *
add_objc_proc_type(c, call, return_type, param_types);
}
-gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, Type *type_hint) {
+gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, ProcTailing tailing, Type *type_hint) {
if (proc != nullptr &&
proc->kind == Ast_BasicDirective) {
ast_node(bd, BasicDirective, proc);
@@ -8241,7 +8241,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
return Expr_Expr;
}
if (inlining != ProcInlining_none) {
- error(call, "Inlining operators are not allowed on built-in procedures");
+ error(call, "Inlining directives are not allowed on built-in procedures");
+ }
+ if (tailing != ProcTailing_none) {
+ error(call, "Tailing directives are not allowed on built-in procedures");
}
} else {
if (proc != nullptr) {
@@ -8383,6 +8386,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
}
bool is_call_inlined = false;
+ bool is_call_tailed = true;
switch (inlining) {
case ProcInlining_inline:
@@ -8417,6 +8421,23 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
}
}
+ switch (tailing) {
+ case ProcTailing_none:
+ break;
+ case ProcTailing_must_tail:
+ is_call_tailed = true;
+ if (c->curr_proc_sig == nullptr || !are_types_identical(c->curr_proc_sig, pt)) {
+ ERROR_BLOCK();
+ gbString a = type_to_string(pt);
+ gbString b = type_to_string(c->curr_proc_sig);
+ error(call, "Use of '#must_tail' of a procedure must have the same type as the procedure it was called within");
+ error_line("\tCall type: %s, parent type: %s", a, b);
+ gb_string_free(b);
+ gb_string_free(a);
+ }
+ break;
+ }
+
{
String invalid;
if (pt->kind == Type_Proc && pt->Proc.require_target_feature.len != 0) {
@@ -11825,7 +11846,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
case_end;
case_ast_node(ce, CallExpr, node);
- return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, type_hint);
+ return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, ce->tailing, type_hint);
case_end;
case_ast_node(de, DerefExpr, node);
@@ -12566,6 +12587,12 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan
case_end;
case_ast_node(ce, CallExpr, node);
+ switch (ce->tailing) {
+ case ProcTailing_must_tail:
+ str = gb_string_appendc(str, "#must_tail ");
+ break;
+ }
+
switch (ce->inlining) {
case ProcInlining_inline:
str = gb_string_appendc(str, "#force_inline ");