mirror of
https://github.com/vlang/v.git
synced 2025-09-17 19:36:35 -04:00
This commit is contained in:
parent
b58937c9cf
commit
24eac4d74d
@ -1125,7 +1125,11 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
|
||||
if typ.has_flag(.generic) {
|
||||
lambda_ret_gt_name := c.table.type_to_str(typ)
|
||||
idx := func.generic_names.index(lambda_ret_gt_name)
|
||||
typ = node.concrete_types[idx]
|
||||
if idx < node.concrete_types.len {
|
||||
typ = node.concrete_types[idx]
|
||||
} else {
|
||||
typ = ast.void_type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1806,15 +1806,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 && 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(),
|
||||
node.concrete_types)
|
||||
{
|
||||
call_arg.expr.func.decl.ninstances++
|
||||
}
|
||||
}
|
||||
c.handle_generic_lambda_arg(node, mut call_arg.expr)
|
||||
continue
|
||||
}
|
||||
c.error('${err.msg()} in argument ${i + 1} to `${fn_name}`', call_arg.pos)
|
||||
@ -2793,6 +2785,10 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||
c.error('${err.msg()} in argument ${i + 1} to `${left_sym.name}.${method_name}`',
|
||||
arg.pos)
|
||||
}
|
||||
if mut arg.expr is ast.LambdaExpr {
|
||||
// Calling fn is generic and lambda arg also is generic
|
||||
c.handle_generic_lambda_arg(node, mut arg.expr)
|
||||
}
|
||||
param_typ_sym := c.table.sym(exp_arg_typ)
|
||||
if param_typ_sym.kind == .struct && got_arg_typ !in [ast.voidptr_type, ast.nil_type]
|
||||
&& !c.check_multiple_ptr_match(got_arg_typ, param.typ, param, arg) {
|
||||
@ -2871,6 +2867,17 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||
return node.return_type
|
||||
}
|
||||
|
||||
fn (mut c Checker) handle_generic_lambda_arg(node &ast.CallExpr, mut lambda ast.LambdaExpr) {
|
||||
// Calling fn is generic and lambda arg also is generic
|
||||
if node.concrete_types.len > 0 && lambda.func != unsafe { nil }
|
||||
&& lambda.func.decl.generic_names.len > 0 {
|
||||
lambda.call_ctx = unsafe { node }
|
||||
if c.table.register_fn_concrete_types(lambda.func.decl.fkey(), node.concrete_types) {
|
||||
lambda.func.decl.ninstances++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) spawn_expr(mut node ast.SpawnExpr) ast.Type {
|
||||
ret_type := c.call_expr(mut node.call_expr)
|
||||
if node.call_expr.or_block.kind != .absent {
|
||||
|
34
vlib/v/tests/generics/generic_method_lambda_arg_test.v
Normal file
34
vlib/v/tests/generics/generic_method_lambda_arg_test.v
Normal file
@ -0,0 +1,34 @@
|
||||
module main
|
||||
|
||||
fn test_main() {
|
||||
my := MyError{
|
||||
path: 'err msg'
|
||||
}
|
||||
p := my.to[string](|m| m.path)
|
||||
p2 := my.to_str(|m| m.path)
|
||||
println(p)
|
||||
println(p2)
|
||||
|
||||
assert p == p2
|
||||
}
|
||||
|
||||
struct MyError {
|
||||
pub:
|
||||
path string
|
||||
}
|
||||
|
||||
fn (e &MyError) msg() string {
|
||||
return e.path
|
||||
}
|
||||
|
||||
fn (e &MyError) code() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
fn (e &MyError) to[T](func fn (MyError) T) T {
|
||||
return func(e)
|
||||
}
|
||||
|
||||
fn (e &MyError) to_str(func fn (MyError) string) string {
|
||||
return func(e)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user