mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
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{} }
|
typ_sym.find_method_with_generic_parent(imethod.name) or { ast.Fn{} }
|
||||||
}
|
}
|
||||||
if imethod.return_type.has_flag(.generic) {
|
if imethod.return_type.has_flag(.generic) {
|
||||||
if method.return_type !in inferred_types {
|
mut inferred_type := method.return_type
|
||||||
inferred_types << 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 {
|
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 has_field {
|
||||||
if sym.mod != c.mod && !field.is_pub && sym.language != .c {
|
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
|
27 | t := <-g.ch
|
||||||
28 | handle(t)
|
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>
|
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 | }
|
30 | }
|
||||||
31 |
|
31 |
|
||||||
|
28
vlib/v/tests/generics_fn_return_generic_interface_test.v
Normal file
28
vlib/v/tests/generics_fn_return_generic_interface_test.v
Normal file
@ -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…
x
Reference in New Issue
Block a user