all: support generic `chan` (#8188)
parent
35279a15a4
commit
5cc591b2b6
|
@ -1523,6 +1523,14 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
idx := c.table.find_or_register_array(call_expr.generic_type)
|
||||
return table.new_type(idx)
|
||||
}
|
||||
} else if return_sym.kind == .chan {
|
||||
elem_info := return_sym.info as table.Chan
|
||||
elem_sym := c.table.get_type_symbol(elem_info.elem_type)
|
||||
if elem_sym.name == 'T' {
|
||||
idx := c.table.find_or_register_chan(elem_info.elem_type, elem_info.elem_type.nr_muls() >
|
||||
0)
|
||||
return table.new_type(idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
if call_expr.generic_type.is_full() && !method.is_generic {
|
||||
|
@ -1862,6 +1870,12 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
typ := table.new_type(idx)
|
||||
call_expr.return_type = typ
|
||||
return typ
|
||||
} else if return_sym.kind == .chan && return_sym.name.contains('T') {
|
||||
idx := c.table.find_or_register_chan(call_expr.generic_type, call_expr.generic_type.nr_muls() >
|
||||
0)
|
||||
typ := table.new_type(idx)
|
||||
call_expr.return_type = typ
|
||||
return typ
|
||||
}
|
||||
}
|
||||
if call_expr.generic_type.is_full() && !f.is_generic {
|
||||
|
|
|
@ -681,17 +681,20 @@ typedef struct {
|
|||
if typ.name != 'chan' {
|
||||
g.type_definitions.writeln('typedef chan $typ.cname;')
|
||||
chan_inf := typ.chan_info()
|
||||
el_stype := g.typ(chan_inf.elem_type)
|
||||
g.channel_definitions.writeln('
|
||||
chan_elem_type := chan_inf.elem_type
|
||||
if !chan_elem_type.has_flag(.generic) {
|
||||
el_stype := g.typ(chan_elem_type)
|
||||
g.channel_definitions.writeln('
|
||||
static inline $el_stype __${typ.cname}_popval($typ.cname ch) {
|
||||
$el_stype val;
|
||||
sync__Channel_try_pop_priv(ch, &val, false);
|
||||
return val;
|
||||
}')
|
||||
g.channel_definitions.writeln('
|
||||
g.channel_definitions.writeln('
|
||||
static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) {
|
||||
sync__Channel_try_push_priv(ch, &val, false);
|
||||
}')
|
||||
}
|
||||
}
|
||||
}
|
||||
.map {
|
||||
|
@ -712,7 +715,7 @@ pub fn (mut g Gen) write_fn_typesymbol_declaration(sym table.TypeSymbol) {
|
|||
func := info.func
|
||||
is_fn_sig := func.name == ''
|
||||
not_anon := !info.is_anon
|
||||
if !info.has_decl && (not_anon || is_fn_sig) {
|
||||
if !info.has_decl && (not_anon || is_fn_sig) && !func.return_type.has_flag(.generic) {
|
||||
fn_name := sym.cname
|
||||
g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
||||
for i, param in func.params {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
fn mk_chan<T>(f fn () T) chan T {
|
||||
gench := chan T{cap: 1}
|
||||
// // This does not work, yet
|
||||
// go fn(ch2 chan T, f2 fn() T) {
|
||||
// res := f2()
|
||||
// ch2 <- res
|
||||
// }(gench, f)
|
||||
return gench
|
||||
}
|
||||
|
||||
fn g(x f64, y f64) f64 {
|
||||
return x * x + y * y
|
||||
}
|
||||
|
||||
fn test_generic_chan_return() {
|
||||
ch := mk_chan<f64>(fn () f64 {
|
||||
return g(3, 4)
|
||||
})
|
||||
ch <- 13.4
|
||||
res := <-ch
|
||||
assert res == 13.4
|
||||
}
|
Loading…
Reference in New Issue