From 81f0413b1faaaae3c309827916b4738ce60c5fa1 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 2 Oct 2024 09:14:04 -0300 Subject: [PATCH 1/4] fix --- vlib/v/checker/fn.v | 2 +- vlib/v/checker/return.v | 5 ++--- vlib/v/checker/str.v | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index de4ffb74183909..5e85a943a9c64f 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1608,7 +1608,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. } if mut call_arg.expr is ast.LambdaExpr { // Calling fn is generic and lambda arg also is generic - if node.concrete_types.len > 0 + if node.concrete_types.len > 0 && call_arg.expr.func != unsafe { nil } && call_arg.expr.func.decl.generic_names.len > 0 { call_arg.expr.call_ctx = unsafe { node } if c.table.register_fn_concrete_types(call_arg.expr.func.decl.fkey(), diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 807e4153efc507..f85f9d03bbba30 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -261,9 +261,8 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { } else { got_type_sym.name } - // ignore generic casting expr on lambda in this phase - if c.inside_lambda && exp_type.has_flag(.generic) - && node.exprs[expr_idxs[i]] is ast.CastExpr { + // ignore generic lambda return in this phase + if c.inside_lambda && exp_type.has_flag(.generic) { continue } c.error('cannot use `${got_type_name}` as ${c.error_type_name(exp_type)} in return argument', diff --git a/vlib/v/checker/str.v b/vlib/v/checker/str.v index 142a4e42e6b617..f6af04edd5bd1d 100644 --- a/vlib/v/checker/str.v +++ b/vlib/v/checker/str.v @@ -75,7 +75,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type { if fmt == `_` { // set default representation for type if none has been given fmt = c.get_default_fmt(ftyp, typ) if fmt == `_` { - if typ != ast.void_type { + if typ != ast.void_type && !typ.has_flag(.generic) { c.error('no known default format for type `${c.table.get_type_name(ftyp)}`', node.fmt_poss[i]) } From a7b49ce25f08b2d9a33ccf394fc82b462562401f Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 2 Oct 2024 09:25:09 -0300 Subject: [PATCH 2/4] new test --- vlib/v/tests/generics/lamda_param_and_ret_test.v | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 vlib/v/tests/generics/lamda_param_and_ret_test.v diff --git a/vlib/v/tests/generics/lamda_param_and_ret_test.v b/vlib/v/tests/generics/lamda_param_and_ret_test.v new file mode 100644 index 00000000000000..fb639abd0c2727 --- /dev/null +++ b/vlib/v/tests/generics/lamda_param_and_ret_test.v @@ -0,0 +1,7 @@ +import arrays + +fn test_main() { + items := ['item1', 'item2', 'item3'] + list := arrays.map_indexed[string, string](items, |i, item| '${i}. ${item}') + assert list == ['0. item1', '1. item2', '2. item3'] +} From bf5f70ff668adb8e4725948ceb90d2b1125dc4b9 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 3 Oct 2024 08:37:58 -0300 Subject: [PATCH 3/4] fix --- vlib/v/ast/table.v | 3 ++- vlib/v/checker/checker.v | 9 +++++++++ vlib/v/checker/fn.v | 4 ++++ vlib/v/checker/str.v | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index f728acb6a86f8d..7481543176a0aa 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -37,7 +37,8 @@ pub mut: panic_handler FnPanicHandler = default_table_panic_handler panic_userdata voidptr = unsafe { nil } // can be used to pass arbitrary data to panic_handler; panic_npanics int - cur_fn &FnDecl = unsafe { nil } // previously stored in Checker.cur_fn and Gen.cur_fn + cur_fn &FnDecl = unsafe { nil } // previously stored in Checker.cur_fn and Gen.cur_fn + cur_lambda &LambdaExpr = unsafe { nil } // current lambda node cur_concrete_types []Type // current concrete types, e.g. gostmts int // how many `go` statements there were in the parsed files. // When table.gostmts > 0, __VTHREADS__ is defined, which can be checked with `$if threads {` diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 200af1fc62a501..032e3379e5444c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2735,6 +2735,13 @@ fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type { { return t_typ } + if c.inside_lambda && c.table.cur_lambda.call_ctx != unsafe { nil } { + if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_lambda.func.decl.generic_names, + c.table.cur_lambda.call_ctx.concrete_types) + { + return t_typ + } + } } } return typ @@ -2971,8 +2978,10 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type { } ast.LambdaExpr { c.inside_lambda = true + c.table.cur_lambda = unsafe { &node } defer { c.inside_lambda = false + c.table.cur_lambda = unsafe { nil } } return c.lambda_expr(mut node, c.expected_type) } diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 5e85a943a9c64f..7cb88d514f7fc4 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1234,6 +1234,10 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. for i, mut call_arg in node.args { if call_arg.expr is ast.CallExpr { node.args[i].typ = c.expr(mut call_arg.expr) + } else if mut call_arg.expr is ast.LambdaExpr { + if node.concrete_types.len > 0 { + call_arg.expr.call_ctx = unsafe { node } + } } } c.check_expected_arg_count(mut node, func) or { return func.return_type } diff --git a/vlib/v/checker/str.v b/vlib/v/checker/str.v index f6af04edd5bd1d..57b64fdc26e90b 100644 --- a/vlib/v/checker/str.v +++ b/vlib/v/checker/str.v @@ -44,7 +44,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type { inside_interface_deref_save := c.inside_interface_deref c.inside_interface_deref = true for i, mut expr in node.exprs { - mut ftyp := c.expr(mut expr) + mut ftyp := c.unwrap_generic(c.expr(mut expr)) ftyp = c.check_expr_option_or_result_call(expr, ftyp) if c.comptime.is_comptime_var(expr) { ctyp := c.comptime.get_comptime_var_type(expr) @@ -75,7 +75,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type { if fmt == `_` { // set default representation for type if none has been given fmt = c.get_default_fmt(ftyp, typ) if fmt == `_` { - if typ != ast.void_type && !typ.has_flag(.generic) { + if typ != ast.void_type { c.error('no known default format for type `${c.table.get_type_name(ftyp)}`', node.fmt_poss[i]) } From eebc50201ddbe063bf85d4457f3f4f1a356d51db Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 3 Oct 2024 10:39:32 -0300 Subject: [PATCH 4/4] fix --- vlib/v/checker/str.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlib/v/checker/str.v b/vlib/v/checker/str.v index 57b64fdc26e90b..142a4e42e6b617 100644 --- a/vlib/v/checker/str.v +++ b/vlib/v/checker/str.v @@ -44,7 +44,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type { inside_interface_deref_save := c.inside_interface_deref c.inside_interface_deref = true for i, mut expr in node.exprs { - mut ftyp := c.unwrap_generic(c.expr(mut expr)) + mut ftyp := c.expr(mut expr) ftyp = c.check_expr_option_or_result_call(expr, ftyp) if c.comptime.is_comptime_var(expr) { ctyp := c.comptime.get_comptime_var_type(expr)