1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix generic method on aliases receiver type (#14729)

This commit is contained in:
yuyi 2022-06-09 20:36:31 +08:00 committed by GitHub
parent e1360ccf8c
commit 784361f153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 11 deletions

View File

@ -619,7 +619,7 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr
mut to_set := ast.void_type mut to_set := ast.void_type
// resolve generic struct receiver // resolve generic struct receiver
if node.is_method && param.typ.has_flag(.generic) { if node.is_method && param.typ.has_flag(.generic) {
sym := c.table.sym(node.receiver_type) sym := c.table.final_sym(node.receiver_type)
match sym.info { match sym.info {
ast.Struct, ast.Interface, ast.SumType { ast.Struct, ast.Interface, ast.SumType {
if !isnil(c.table.cur_fn) && c.table.cur_fn.generic_names.len > 0 { // in generic fn if !isnil(c.table.cur_fn) && c.table.cur_fn.generic_names.len > 0 { // in generic fn

View File

@ -1193,14 +1193,14 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
method = m method = m
has_method = true has_method = true
} else { } else {
if left_sym.kind in [.struct_, .sum_type, .interface_] { if final_left_sym.kind in [.struct_, .sum_type, .interface_] {
mut parent_type := ast.void_type mut parent_type := ast.void_type
if left_sym.info is ast.Struct { if final_left_sym.info is ast.Struct {
parent_type = left_sym.info.parent_type parent_type = final_left_sym.info.parent_type
} else if left_sym.info is ast.SumType { } else if final_left_sym.info is ast.SumType {
parent_type = left_sym.info.parent_type parent_type = final_left_sym.info.parent_type
} else if left_sym.info is ast.Interface { } else if final_left_sym.info is ast.Interface {
parent_type = left_sym.info.parent_type parent_type = final_left_sym.info.parent_type
} }
if parent_type != 0 { if parent_type != 0 {
type_sym := c.table.sym(parent_type) type_sym := c.table.sym(parent_type)
@ -1214,7 +1214,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
if !has_method { if !has_method {
has_method = true has_method = true
mut embed_types := []ast.Type{} mut embed_types := []ast.Type{}
method, embed_types = c.table.find_method_from_embeds(left_sym, method_name) or { method, embed_types = c.table.find_method_from_embeds(final_left_sym, method_name) or {
if err.msg() != '' { if err.msg() != '' {
c.error(err.msg(), node.pos) c.error(err.msg(), node.pos)
} }
@ -1226,14 +1226,14 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
node.from_embed_types = embed_types node.from_embed_types = embed_types
} }
} }
if left_sym.kind == .aggregate { if final_left_sym.kind == .aggregate {
// the error message contains the problematic type // the error message contains the problematic type
unknown_method_msg = err.msg() unknown_method_msg = err.msg()
} }
} }
if has_method { if has_method {
// x is Bar<T>, x.foo() -> x.foo<T>() // x is Bar<T>, x.foo() -> x.foo<T>()
rec_sym := c.table.sym(node.left_type) rec_sym := c.table.final_sym(node.left_type)
rec_is_generic := left_type.has_flag(.generic) rec_is_generic := left_type.has_flag(.generic)
mut rec_concrete_types := []ast.Type{} mut rec_concrete_types := []ast.Type{}
if rec_sym.info is ast.Struct { if rec_sym.info is ast.Struct {

View File

@ -0,0 +1,17 @@
module main
struct Container<T> {
value T
}
fn (c Container<T>) id() int {
return 1
}
type Text = Container<string>
fn test_generic_method_on_receiver_aliases_type() {
t := Text{'test'}
println(t.id())
assert t.id() == 1
}