* 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