From 953eb489c93bd6bebd59ddc0d0159aac7759aba9 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:18 +0300 Subject: [PATCH] cgen: fix c error while migrating vpm to veb (fixes #24044) --- vlib/v/checker/fn.v | 44 ++++++++++++++----- vlib/v/gen/c/comptime.v | 27 ++++++++++-- .../veb_custom_context_route_call.c.must_have | 2 + .../veb_custom_context_route_call.html | 1 + .../testdata/veb_custom_context_route_call.vv | 23 ++++++++++ 5 files changed, 83 insertions(+), 14 deletions(-) create mode 100644 vlib/v/gen/c/testdata/veb_custom_context_route_call.c.must_have create mode 100644 vlib/v/gen/c/testdata/veb_custom_context_route_call.html create mode 100644 vlib/v/gen/c/testdata/veb_custom_context_route_call.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 1646f5789..94ebdf0a5 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -3640,16 +3640,8 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) ! return } } - // Implicit context first arg? - /* - first_typ := f.params[0].typ - first_sym := c.table.sym(first_typ) - */ - if last_sym.info is ast.Struct { - if last_sym.name == 'main.Context' && last_required_param.name == 'ctx' { // TODO use int comparison for perf - // c.error('got ctx ${first_sym.name}', node.pos) - return - } + if c.try_add_implicit_veb_context_arg(mut node, f) { + return } } c.fn_call_error_have_want( @@ -3686,6 +3678,38 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) ! } } +fn (mut c Checker) try_add_implicit_veb_context_arg(mut node ast.CallExpr, f &ast.Fn) bool { + if f.params.len == 0 || f.params.last().name != 'ctx' || !c.has_veb_context(f.params.last().typ) { + return false + } + scope := if c.fn_scope != unsafe { nil } { c.fn_scope } else { node.scope } + if scope == unsafe { nil } { + return false + } + ctx_var := scope.find_var('ctx') or { return false } + node.args << ast.CallArg{ + is_mut: f.params.last().is_mut + typ: ctx_var.typ + pos: node.pos + expr: ast.Ident{ + language: .v + tok_kind: .name + pos: node.pos + scope: scope + obj: *ctx_var + mod: c.mod + name: 'ctx' + kind: .variable + info: ast.IdentVar{ + typ: ctx_var.typ + is_mut: ctx_var.is_mut + } + is_mut: f.params.last().is_mut + } + } + return true +} + @[params] struct HaveWantParams { nr_params int diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index bf423fdf2..1388679f6 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -8,6 +8,27 @@ import v.ast import v.util import v.type_resolver +fn (g &Gen) veb_context_html_arg() string { + if g.fn_decl.params.len < 2 { + return 'ctx' + } + ctx_param := g.fn_decl.params[1] + ctx_sym := g.table.final_sym(ctx_param.typ) + if ctx_sym.name == 'veb.Context' { + return ctx_param.name + } + if ctx_sym.info is ast.Struct { + for embed in ctx_sym.info.embeds { + embed_sym := g.table.sym(embed) + if embed_sym.name == 'veb.Context' { + dot := if ctx_param.typ.is_ptr() { '->' } else { '.' } + return '&${ctx_param.name}${dot}${embed_sym.embed_name()}' + } + } + } + return ctx_param.name +} + fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) { left_type := g.resolved_expr_type(node.left, node.left_type) is_interface_field := g.table.sym(left_type).kind == .interface @@ -154,11 +175,9 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) { if is_html { // return a vweb or x.vweb html template if is_veb { - ctx_name := g.fn_decl.params[1].name - g.writeln('veb__Context_html(${ctx_name}, _tmpl_res_${fn_name});') + g.writeln('veb__Context_html(${g.veb_context_html_arg()}, _tmpl_res_${fn_name});') } else if is_x_vweb { - ctx_name := g.fn_decl.params[1].name - g.writeln('x__vweb__Context_html(${ctx_name}, _tmpl_res_${fn_name});') + g.writeln('x__vweb__Context_html(${g.veb_context_html_arg()}, _tmpl_res_${fn_name});') } else { // old vweb: app_name := g.fn_decl.params[0].name diff --git a/vlib/v/gen/c/testdata/veb_custom_context_route_call.c.must_have b/vlib/v/gen/c/testdata/veb_custom_context_route_call.c.must_have new file mode 100644 index 000000000..c5f17aeb8 --- /dev/null +++ b/vlib/v/gen/c/testdata/veb_custom_context_route_call.c.must_have @@ -0,0 +1,2 @@ +return main__App_new(app, ctx); +veb__Context_html(&ctx->Context, _tmpl_res_ diff --git a/vlib/v/gen/c/testdata/veb_custom_context_route_call.html b/vlib/v/gen/c/testdata/veb_custom_context_route_call.html new file mode 100644 index 000000000..cb1df192b --- /dev/null +++ b/vlib/v/gen/c/testdata/veb_custom_context_route_call.html @@ -0,0 +1 @@ +
Route helper page
diff --git a/vlib/v/gen/c/testdata/veb_custom_context_route_call.vv b/vlib/v/gen/c/testdata/veb_custom_context_route_call.vv new file mode 100644 index 000000000..541e90ad7 --- /dev/null +++ b/vlib/v/gen/c/testdata/veb_custom_context_route_call.vv @@ -0,0 +1,23 @@ +module main + +import veb + +struct App {} + +struct Context { + veb.Context +} + +fn (mut app App) new() veb.Result { + return $veb.html('veb_custom_context_route_call.html') +} + +fn (mut app App) create(mut ctx Context) veb.Result { + return app.new() +} + +fn main() { + mut app := App{} + mut ctx := Context{} + _ = app.create(mut ctx) +} -- 2.39.5