* 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 {
|
if method.generic_names.len > 0 {
|
||||||
continue
|
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
|
// str method, allow type with str method if fn arg is string
|
||||||
// Passing an int or a string array produces a c error here
|
// Passing an int or a string array produces a c error here
|
||||||
// Deleting this condition results in propper V error messages
|
// 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 {
|
if method.generic_names.len != call_expr.concrete_types.len {
|
||||||
// no type arguments given in call, attempt implicit instantiation
|
// no type arguments given in call, attempt implicit instantiation
|
||||||
c.infer_fn_generic_types(method, mut call_expr)
|
c.infer_fn_generic_types(method, mut call_expr)
|
||||||
|
concrete_types = call_expr.concrete_types
|
||||||
}
|
}
|
||||||
// resolve return generics struct to concrete type
|
// resolve return generics struct to concrete type
|
||||||
if method.generic_names.len > 0 && method.return_type.has_flag(.generic) {
|
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 {
|
} else {
|
||||||
call_expr.return_type = method.return_type
|
call_expr.return_type = method.return_type
|
||||||
}
|
}
|
||||||
if call_expr.concrete_types.len > 0 && method.return_type != 0 {
|
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,
|
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
|
call_expr.return_type = typ
|
||||||
return 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())
|
c.type_implements(typ, param.typ, call_arg.expr.position())
|
||||||
continue
|
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
|
// str method, allow type with str method if fn arg is string
|
||||||
// Passing an int or a string array produces a c error here
|
// Passing an int or a string array produces a c error here
|
||||||
// Deleting this condition results in propper V error messages
|
// 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 {
|
if func.generic_names.len != call_expr.concrete_types.len {
|
||||||
// no type arguments given in call, attempt implicit instantiation
|
// no type arguments given in call, attempt implicit instantiation
|
||||||
c.infer_fn_generic_types(func, mut call_expr)
|
c.infer_fn_generic_types(func, mut call_expr)
|
||||||
|
concrete_types = call_expr.concrete_types
|
||||||
}
|
}
|
||||||
if func.generic_names.len > 0 {
|
if func.generic_names.len > 0 {
|
||||||
for i, call_arg in call_expr.args {
|
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)
|
if param.typ.has_flag(.generic)
|
||||||
&& func.generic_names.len == call_expr.concrete_types.len {
|
&& func.generic_names.len == call_expr.concrete_types.len {
|
||||||
if unwrap_typ := c.table.resolve_generic_to_concrete(param.typ, func.generic_names,
|
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)
|
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
|
// resolve return generics struct to concrete type
|
||||||
if func.generic_names.len > 0 && func.return_type.has_flag(.generic) {
|
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 {
|
} else {
|
||||||
call_expr.return_type = func.return_type
|
call_expr.return_type = func.return_type
|
||||||
}
|
}
|
||||||
if call_expr.concrete_types.len > 0 && func.return_type != 0 {
|
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,
|
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
|
call_expr.return_type = typ
|
||||||
return typ
|
return typ
|
||||||
|
|
|
@ -853,7 +853,15 @@ pub fn (mut g Gen) write_fn_typesymbol_declaration(sym ast.TypeSymbol) {
|
||||||
func := info.func
|
func := info.func
|
||||||
is_fn_sig := func.name == ''
|
is_fn_sig := func.name == ''
|
||||||
not_anon := !info.is_anon
|
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
|
fn_name := sym.cname
|
||||||
g.type_definitions.write_string('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
g.type_definitions.write_string('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
||||||
for i, param in func.params {
|
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