all: support generic `chan` (#8188)

pull/8190/head
Uwe Krüger 2021-01-18 18:37:45 +01:00 committed by GitHub
parent 35279a15a4
commit 5cc591b2b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 4 deletions

View File

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

View File

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

View File

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