mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
parent
f1216090f7
commit
57e4ba4cd0
@ -272,6 +272,27 @@ fn (mut c Checker) resolve_generic_interface(typ ast.Type, interface_type ast.Ty
|
||||
ret_typ = ret_typ.clear_flag(.optional)
|
||||
}
|
||||
inferred_type = ret_typ
|
||||
} else if imret_sym.info is ast.SumType && mret_sym.info is ast.SumType {
|
||||
im_generic_names := imret_sym.info.generic_types.map(c.table.sym(it).name)
|
||||
if gt_name in im_generic_names
|
||||
&& imret_sym.info.generic_types.len == mret_sym.info.concrete_types.len {
|
||||
idx := im_generic_names.index(gt_name)
|
||||
inferred_type = mret_sym.info.concrete_types[idx]
|
||||
}
|
||||
} else if imret_sym.info is ast.Interface && mret_sym.info is ast.Interface {
|
||||
im_generic_names := imret_sym.info.generic_types.map(c.table.sym(it).name)
|
||||
if gt_name in im_generic_names
|
||||
&& imret_sym.info.generic_types.len == mret_sym.info.concrete_types.len {
|
||||
idx := im_generic_names.index(gt_name)
|
||||
inferred_type = mret_sym.info.concrete_types[idx]
|
||||
}
|
||||
} else if imret_sym.info is ast.Struct && mret_sym.info is ast.Struct {
|
||||
im_generic_names := imret_sym.info.generic_types.map(c.table.sym(it).name)
|
||||
if gt_name in im_generic_names
|
||||
&& imret_sym.info.generic_types.len == mret_sym.info.concrete_types.len {
|
||||
idx := im_generic_names.index(gt_name)
|
||||
inferred_type = mret_sym.info.concrete_types[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, iparam in imethod.params {
|
||||
|
81
vlib/v/tests/generics_interface_with_generic_sumtype_test.v
Normal file
81
vlib/v/tests/generics_interface_with_generic_sumtype_test.v
Normal file
@ -0,0 +1,81 @@
|
||||
// optional.v
|
||||
struct NonValue {}
|
||||
|
||||
pub type Optional<T> = NonValue | T
|
||||
|
||||
pub fn (self Optional<T>) is_some<T>() bool {
|
||||
return self is T
|
||||
}
|
||||
|
||||
pub fn (self Optional<T>) is_none<T>() bool {
|
||||
return !self.is_some()
|
||||
}
|
||||
|
||||
pub fn (self Optional<T>) expect<T>(msg string) T {
|
||||
if self.is_some() {
|
||||
return self as T
|
||||
} else {
|
||||
panic(msg)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (self Optional<T>) unwrap<T>() T {
|
||||
return self.expect('unwrap on a none value')
|
||||
}
|
||||
|
||||
pub fn (self Optional<T>) unwrap_or<T>(default T) T {
|
||||
if self.is_some() {
|
||||
return self as T
|
||||
} else {
|
||||
return default
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (self Optional<T>) unwrap_or_else<T>(else_fn fn () T) T {
|
||||
if self.is_some() {
|
||||
return self as T
|
||||
} else {
|
||||
return else_fn()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn some<T>(value T) Optional<T> {
|
||||
return Optional<T>(value as T)
|
||||
}
|
||||
|
||||
pub fn null<T>() Optional<T> {
|
||||
return Optional<T>(NonValue{})
|
||||
}
|
||||
|
||||
// iter.v
|
||||
pub interface Iterator<T> {
|
||||
mut:
|
||||
next() Optional<T>
|
||||
}
|
||||
|
||||
pub fn (mut self Iterator<T>) count<T>() int {
|
||||
mut count := 0
|
||||
for self.next().is_some() {
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
struct EmptyIter<T> {
|
||||
value NonValue
|
||||
}
|
||||
|
||||
fn (mut self EmptyIter<T>) next<T>() Optional<T> {
|
||||
return Optional<T>(self.value)
|
||||
}
|
||||
|
||||
// iter_test.v
|
||||
fn test_generics_interface_with_generic_sumtype() {
|
||||
mut iter1 := EmptyIter<u32>{}
|
||||
println(iter1)
|
||||
assert iter1.next().is_none()
|
||||
|
||||
mut iter2 := Iterator<u32>(iter1)
|
||||
println(iter2)
|
||||
assert iter2.count() == 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user