diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f96f277d87..5a57057c9f 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1968,6 +1968,13 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { left_type := c.expr(call_expr.left) c.expected_type = left_type mut is_generic := left_type.has_flag(.generic) + // x is Bar, x.foo() -> x.foo() + if is_generic && call_expr.concrete_types.len == 0 { + rec_sym := c.table.get_type_symbol(left_type) + if rec_sym.info is ast.Struct { + call_expr.concrete_types = rec_sym.info.generic_types + } + } call_expr.left_type = left_type // Set default values for .return_type & .receiver_type too, // or there will be hard to diagnose 0 type panics in cgen. diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index b2834340f5..73c509ef51 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -831,6 +831,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { // left & left_type will be `x` and `x type` in `x.fieldfn()` // will be `0` for `foo()` mut is_interface_call := false + mut is_selector_call := false if node.left_type != 0 { left_sym := g.table.get_type_symbol(node.left_type) if left_sym.kind == .interface_ { @@ -843,6 +844,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { } else { g.write('.') } + is_selector_call = true } mut name := node.name is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic'] @@ -914,7 +916,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { panic('cgen: obf name "$key" not found, this should never happen') } } - name = g.generic_fn_name(node.concrete_types, name, false) + if !is_selector_call { + name = g.generic_fn_name(node.concrete_types, name, false) + } // TODO2 // cgen shouldn't modify ast nodes, this should be moved // g.generate_tmp_autofree_arg_vars(node, name) diff --git a/vlib/v/tests/generics_with_multi_generics_struct_types_test.v b/vlib/v/tests/generics_with_multi_generics_struct_types_test.v new file mode 100644 index 0000000000..36835cb473 --- /dev/null +++ b/vlib/v/tests/generics_with_multi_generics_struct_types_test.v @@ -0,0 +1,19 @@ +struct Animal { + metadata T +} + +fn (a Animal) get() T { + return a.metadata +} + +fn extract(x Animal) T { + return x.get() +} + +fn test_generics_with_multi_generic_struct_types() { + a := Animal{123} + b := Animal{'456'} + + assert extract(a) == 123 + assert extract(b) == '456' +}