parent
11a7899690
commit
8b8f496762
|
@ -2991,8 +2991,12 @@ fn (mut c Checker) resolve_generic_interface(typ ast.Type, interface_type ast.Ty
|
|||
typ_sym.find_method_with_generic_parent(imethod.name) or { ast.Fn{} }
|
||||
}
|
||||
if imethod.return_type.has_flag(.generic) {
|
||||
if method.return_type !in inferred_types {
|
||||
inferred_types << method.return_type
|
||||
mut inferred_type := method.return_type
|
||||
if imethod.return_type.has_flag(.optional) {
|
||||
inferred_type = inferred_type.clear_flag(.optional)
|
||||
}
|
||||
if inferred_type !in inferred_types {
|
||||
inferred_types << inferred_type
|
||||
}
|
||||
}
|
||||
for i, iparam in imethod.params {
|
||||
|
@ -3362,6 +3366,33 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
if typ.has_flag(.generic) && !has_field {
|
||||
gs := c.table.get_type_symbol(typ)
|
||||
if f := c.table.find_field(gs, field_name) {
|
||||
has_field = true
|
||||
field = f
|
||||
} else {
|
||||
// look for embedded field
|
||||
if gs.info is ast.Struct {
|
||||
mut found_fields := []ast.StructField{}
|
||||
mut embed_of_found_fields := []ast.Type{}
|
||||
for embed in gs.info.embeds {
|
||||
embed_sym := c.table.get_type_symbol(embed)
|
||||
if f := c.table.find_field(embed_sym, field_name) {
|
||||
found_fields << f
|
||||
embed_of_found_fields << embed
|
||||
}
|
||||
}
|
||||
if found_fields.len == 1 {
|
||||
field = found_fields[0]
|
||||
has_field = true
|
||||
node.from_embed_type = embed_of_found_fields[0]
|
||||
} else if found_fields.len > 1 {
|
||||
c.error('ambiguous field `$field_name`', node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if has_field {
|
||||
if sym.mod != c.mod && !field.is_pub && sym.language != .c {
|
||||
|
|
|
@ -5,13 +5,6 @@ vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:26:1: error: g
|
|||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
27 | t := <-g.ch
|
||||
28 | handle(t)
|
||||
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:27:7: error: <- operator can only be used with `chan` types
|
||||
25 |
|
||||
26 | fn g_worker(g Generic<T>) {
|
||||
27 | t := <-g.ch
|
||||
| ~~
|
||||
28 | handle(t)
|
||||
29 | // println("${t.msg}")
|
||||
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:32:1: error: generic function declaration must specify generic type names, e.g. foo<T>
|
||||
30 | }
|
||||
31 |
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
interface Iter<T> {
|
||||
next() ?T
|
||||
}
|
||||
|
||||
struct ArrayIter<T> {
|
||||
data []T
|
||||
}
|
||||
|
||||
fn (mut i ArrayIter<T>) next<T>() ?T {
|
||||
if i.data.len == 0 {
|
||||
return none
|
||||
}
|
||||
return i.data[0]
|
||||
}
|
||||
|
||||
fn iter<T>(arr []T) Iter<T> {
|
||||
return ArrayIter<T>{
|
||||
data: arr
|
||||
}
|
||||
}
|
||||
|
||||
fn test_generics_fn_return_generic_interface() {
|
||||
x := iter([1, 2, 3])
|
||||
println(x)
|
||||
y := x.next() or { 0 }
|
||||
println(y)
|
||||
assert y == 1
|
||||
}
|
Loading…
Reference in New Issue