From 9ca89235b544cb153d685d9e493b53cb9da4281d Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 15:17:45 +0300 Subject: [PATCH] checker: fix checker error for veb handler param type (fixes #24870) --- vlib/v/checker/fn.v | 18 +++++++++++++++++- .../tests/veb_handler_param_type_err.out | 7 +++++++ .../tests/veb_handler_param_type_err.vv | 19 +++++++++++++++++++ vlib/veb/README.md | 2 ++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/veb_handler_param_type_err.out create mode 100644 vlib/v/checker/tests/veb_handler_param_type_err.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 1a2e790ef..87b588068 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -839,8 +839,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { // Register implicit context var typ_veb_result := c.table.get_veb_result_type_idx() // c.table.find_type('veb.Result') if node.is_method && node.return_type == typ_veb_result { + is_veb_app_method := !c.has_veb_context(node.receiver.typ) for param in node.params[1..] { - if c.has_veb_context(param.typ) && !param.is_mut { + if is_veb_app_method && c.has_veb_context(param.typ) && !param.is_mut { c.error('veb app method `${node.name}` must declare context parameter `${param.name}` as mutable, e.g. `mut ${param.name} ${c.table.type_to_str(param.typ)}`', param.pos) break @@ -888,6 +889,15 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { is_mut: true is_stack_obj: false // true }) + if is_veb_app_method { + for param in node.params[1..] { + if c.has_veb_context(param.typ) || c.supports_veb_string_bound_param(param.typ) { + continue + } + c.error('veb app method `${node.name}` parameter `${param.name}` has unsupported type `${c.table.type_to_str(param.typ)}`; parameters after the context are populated from strings and must be `string`, integer, or `bool`', + param.pos) + } + } } c.stmts(mut node.stmts) node_has_top_return := has_top_return(node.stmts) @@ -5117,6 +5127,12 @@ fn (mut c Checker) has_veb_context(typ ast.Type) bool { return false } +fn (mut c Checker) supports_veb_string_bound_param(typ ast.Type) bool { + unaliased_typ := c.table.unalias_num_type(c.unwrap_generic(typ)) + return unaliased_typ == ast.string_type || unaliased_typ.is_int() + || unaliased_typ.idx() == ast.bool_type_idx +} + fn (mut c Checker) check_variadic_arg(arg_expr ast.Expr, typ ast.Type, expected_type ast.Type, param_typ ast.Type, arg_num int, fn_name string, is_method bool, fn_is_variadic bool, is_single_array_arg bool, is_generic_fn bool, call_pos token.Pos, arg_pos token.Pos) { diff --git a/vlib/v/checker/tests/veb_handler_param_type_err.out b/vlib/v/checker/tests/veb_handler_param_type_err.out new file mode 100644 index 000000000..05413e7c7 --- /dev/null +++ b/vlib/v/checker/tests/veb_handler_param_type_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/veb_handler_param_type_err.vv:17:42: error: veb app method `index` parameter `params` has unsupported type `Params`; parameters after the context are populated from strings and must be `string`, integer, or `bool` + 15 | fn main() {} + 16 | + 17 | pub fn (app &App) index(mut ctx Context, params Params) veb.Result { + | ~~~~~~ + 18 | return veb.no_result() + 19 | } diff --git a/vlib/v/checker/tests/veb_handler_param_type_err.vv b/vlib/v/checker/tests/veb_handler_param_type_err.vv new file mode 100644 index 000000000..b534efb3d --- /dev/null +++ b/vlib/v/checker/tests/veb_handler_param_type_err.vv @@ -0,0 +1,19 @@ +module main + +import veb + +struct Params { + offset int +} + +pub struct Context { + veb.Context +} + +pub struct App {} + +fn main() {} + +pub fn (app &App) index(mut ctx Context, params Params) veb.Result { + return veb.no_result() +} diff --git a/vlib/veb/README.md b/vlib/veb/README.md index 83ed23874..d87263ffc 100644 --- a/vlib/veb/README.md +++ b/vlib/veb/README.md @@ -231,6 +231,8 @@ parameters are passed as arguments. V will cast the parameter to any of V's prim To pass a parameter to an endpoint, you simply define it inside an attribute, e. g. `@['/hello/:user]`. After it is defined in the attribute, you have to add it as a function parameter. +Parameters after `ctx` are populated from strings, so they currently must be `string`, +integer, or `bool`. **Example:** -- 2.39.5