diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index d20a6105b7..0b2103c83d 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1058,8 +1058,9 @@ pub fn (mut t Table) resolve_generic_by_names(generic_type Type, generic_names [ // This is used for resolving the generic return type of CallExpr white `unwrap_generic` is used to resolve generic usage in FnDecl. pub fn (mut t Table) resolve_generic_by_types(generic_type Type, generic_types []Type, concrete_types []Type) ?Type { mut sym := t.get_type_symbol(generic_type) - if generic_type in generic_types { - index := generic_types.index(generic_type) + gtype := generic_type.set_nr_muls(0) // resolve &T &&T + if gtype in generic_types { + index := generic_types.index(gtype) typ := concrete_types[index] return typ.derive(generic_type).clear_flag(.generic) } else if sym.kind == .array { diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index b3237538cc..cc63a40710 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -508,6 +508,10 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx if arg.expr.is_auto_deref_var() { to_set = to_set.deref() } + // resolve &T &&T ... + if param.typ.nr_muls() > 0 && to_set.nr_muls() > 0 { + to_set = to_set.set_nr_muls(0) + } // If the parent fn param is a generic too if to_set.has_flag(.generic) { to_set = c.unwrap_generic(to_set) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 6f05ab376e..096a0efc7a 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -844,7 +844,8 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) { fn (mut p Parser) check_fn_mutable_arguments(typ ast.Type, pos token.Position) { sym := p.table.get_type_symbol(typ) - if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] { + if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, + .generic_struct_inst, .sum_type] { return } if typ.is_ptr() || typ.is_pointer() { diff --git a/vlib/v/tests/generics_call_with_reference_arg_test.v b/vlib/v/tests/generics_call_with_reference_arg_test.v new file mode 100644 index 0000000000..5ad195bef6 --- /dev/null +++ b/vlib/v/tests/generics_call_with_reference_arg_test.v @@ -0,0 +1,26 @@ +struct MyStruct { +mut: + pos int + buffer []&T +} + +fn (mut s MyStruct) add(e &T) bool { + s.buffer[0] = e + return true +} + +fn fill(mut s MyStruct) { + s.add(&i64(123)) +} + +fn test_generics_call_with_reference_arg() { + mut s := MyStruct{ + pos: 1 + buffer: []&i64{len: 2} + } + fill(mut s) + println(s.pos) + assert s.pos == 1 + println(s.buffer.len) + assert s.buffer.len == 2 +}