* checker: fix generics with anon generics fn argument * cgen: fix typedef of generics anon fn * fix check generics argument typespull/9900/head
parent
d8bb939072
commit
9f1ac39770
|
@ -1684,7 +1684,7 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
if method.generic_names.len > 0 {
|
||||
continue
|
||||
}
|
||||
c.check_expected_call_arg(got_arg_typ, exp_arg_typ, call_expr.language) or {
|
||||
c.check_expected_call_arg(got_arg_typ, c.unwrap_generic(exp_arg_typ), call_expr.language) or {
|
||||
// str method, allow type with str method if fn arg is string
|
||||
// Passing an int or a string array produces a c error here
|
||||
// Deleting this condition results in propper V error messages
|
||||
|
@ -1758,16 +1758,17 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
if method.generic_names.len != call_expr.concrete_types.len {
|
||||
// no type arguments given in call, attempt implicit instantiation
|
||||
c.infer_fn_generic_types(method, mut call_expr)
|
||||
concrete_types = call_expr.concrete_types
|
||||
}
|
||||
// resolve return generics struct to concrete type
|
||||
if method.generic_names.len > 0 && method.return_type.has_flag(.generic) {
|
||||
c.check_return_generics_struct(method.return_type, mut call_expr, call_expr.concrete_types)
|
||||
c.check_return_generics_struct(method.return_type, mut call_expr, concrete_types)
|
||||
} else {
|
||||
call_expr.return_type = method.return_type
|
||||
}
|
||||
if call_expr.concrete_types.len > 0 && method.return_type != 0 {
|
||||
if typ := c.table.resolve_generic_to_concrete(method.return_type, method.generic_names,
|
||||
call_expr.concrete_types, false)
|
||||
concrete_types, false)
|
||||
{
|
||||
call_expr.return_type = typ
|
||||
return typ
|
||||
|
@ -2248,7 +2249,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
c.type_implements(typ, param.typ, call_arg.expr.position())
|
||||
continue
|
||||
}
|
||||
c.check_expected_call_arg(typ, param.typ, call_expr.language) or {
|
||||
c.check_expected_call_arg(typ, c.unwrap_generic(param.typ), call_expr.language) or {
|
||||
// str method, allow type with str method if fn arg is string
|
||||
// Passing an int or a string array produces a c error here
|
||||
// Deleting this condition results in propper V error messages
|
||||
|
@ -2275,6 +2276,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
if func.generic_names.len != call_expr.concrete_types.len {
|
||||
// no type arguments given in call, attempt implicit instantiation
|
||||
c.infer_fn_generic_types(func, mut call_expr)
|
||||
concrete_types = call_expr.concrete_types
|
||||
}
|
||||
if func.generic_names.len > 0 {
|
||||
for i, call_arg in call_expr.args {
|
||||
|
@ -2289,9 +2291,9 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
if param.typ.has_flag(.generic)
|
||||
&& func.generic_names.len == call_expr.concrete_types.len {
|
||||
if unwrap_typ := c.table.resolve_generic_to_concrete(param.typ, func.generic_names,
|
||||
call_expr.concrete_types, false)
|
||||
concrete_types, false)
|
||||
{
|
||||
c.check_expected_call_arg(typ, unwrap_typ, call_expr.language) or {
|
||||
c.check_expected_call_arg(c.unwrap_generic(typ), unwrap_typ, call_expr.language) or {
|
||||
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
||||
}
|
||||
}
|
||||
|
@ -2300,13 +2302,13 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
}
|
||||
// resolve return generics struct to concrete type
|
||||
if func.generic_names.len > 0 && func.return_type.has_flag(.generic) {
|
||||
c.check_return_generics_struct(func.return_type, mut call_expr, call_expr.concrete_types)
|
||||
c.check_return_generics_struct(func.return_type, mut call_expr, concrete_types)
|
||||
} else {
|
||||
call_expr.return_type = func.return_type
|
||||
}
|
||||
if call_expr.concrete_types.len > 0 && func.return_type != 0 {
|
||||
if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
|
||||
call_expr.concrete_types, false)
|
||||
concrete_types, false)
|
||||
{
|
||||
call_expr.return_type = typ
|
||||
return typ
|
||||
|
|
|
@ -853,7 +853,15 @@ pub fn (mut g Gen) write_fn_typesymbol_declaration(sym ast.TypeSymbol) {
|
|||
func := info.func
|
||||
is_fn_sig := func.name == ''
|
||||
not_anon := !info.is_anon
|
||||
if !info.has_decl && (not_anon || is_fn_sig) && !func.return_type.has_flag(.generic) {
|
||||
mut has_generic_arg := false
|
||||
for param in func.params {
|
||||
if param.typ.has_flag(.generic) {
|
||||
has_generic_arg = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !info.has_decl && (not_anon || is_fn_sig) && !func.return_type.has_flag(.generic)
|
||||
&& !has_generic_arg {
|
||||
fn_name := sym.cname
|
||||
g.type_definitions.write_string('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
||||
for i, param in func.params {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
struct MyStruct<T> {
|
||||
arr []T
|
||||
}
|
||||
|
||||
fn (mut s MyStruct<T>) get_data(pos int) T {
|
||||
return s.arr[pos]
|
||||
}
|
||||
|
||||
fn (mut s MyStruct<T>) iterate(handler fn (T) int) int {
|
||||
mut sum := 0
|
||||
mut i := 0
|
||||
for {
|
||||
k := s.get_data<T>(i)
|
||||
sum += handler(k)
|
||||
i++
|
||||
if i > 4 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
pub fn consume(data int) int {
|
||||
return data
|
||||
}
|
||||
|
||||
fn test_generics_with_anon_generics_fn() {
|
||||
mut s := MyStruct<int>{
|
||||
arr: [1, 2, 3, 4, 5]
|
||||
}
|
||||
y := s.iterate<int>(consume)
|
||||
println(y)
|
||||
assert y == 15
|
||||
}
|
Loading…
Reference in New Issue