Skip to content

Commit

Permalink
parser: fixed struct methods and receiver use different generic names…
Browse files Browse the repository at this point in the history
… than the generic names defined (fix #20365 #20363) (#20397)
  • Loading branch information
shove70 committed Jan 5, 2024
1 parent e2334d8 commit 4e5c597
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
13 changes: 9 additions & 4 deletions vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,16 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if is_method && rec.typ.has_flag(.generic) {
sym := p.table.sym(rec.typ)
if sym.info is ast.Struct {
decl_generic_names := p.types_to_names(sym.info.generic_types, p.tok.pos(),
'sym.info.generic_types') or { return ast.FnDecl{
scope: unsafe { nil }
} }
fn_generic_names := generic_names.clone()
generic_names = p.types_to_names(sym.info.generic_types, p.tok.pos(), 'sym.info.generic_types') or {
return ast.FnDecl{
scope: unsafe { nil }
}
generic_names = p.table.generic_type_names(rec.typ)
if decl_generic_names.len != generic_names.len {
plural := if decl_generic_names.len == 1 { '' } else { 's' }
p.error_with_pos('expected ${decl_generic_names.len} generic parameter${plural}, got ${generic_names.len}',
rec.type_pos)
}
for gname in fn_generic_names {
if gname !in generic_names {
Expand Down
34 changes: 34 additions & 0 deletions vlib/v/tests/generics_method_with_diff_generic_names_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// for issue: 20363
// The generic name used by the methods and receiver is different from the generic name defined by the struct.
struct Foo[T] {
field T
}

fn new_foo[U](arg U) Foo[U] {
return Foo[U]{arg}
}

fn test_using_diff_generic_names() {
foo := new_foo(1)
foo.method_1('hello')
foo.method_2('hello')
}

fn (f Foo[U]) method_1(arg string) {
assert arg == 'hello'
}

fn (f Foo[U]) method_2[U](arg string) {
assert arg == 'hello'
}

// for issue: 20365
// The generic name used by the `str()` method and receiver is different from the generic name defined by the struct.
fn (f Foo[U]) str[U]() string {
return 'hello'
}

fn test_str_override() {
foo := new_foo(1)
assert '${foo}' == 'hello'
}

0 comments on commit 4e5c597

Please sign in to comment.