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

checker: fix generics interface with generic sumtype (fix #15883) (#15892)

This commit is contained in:
yuyi 2022-09-27 21:33:34 +08:00 committed by GitHub
parent f1216090f7
commit 57e4ba4cd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 0 deletions

View File

@ -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 {

View 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
}