checker: check the arity and the kinds of the type parameters in generic struct inits (#13429)
							parent
							
								
									7f29418c63
								
							
						
					
					
						commit
						a21f4563b3
					
				| 
						 | 
					@ -138,6 +138,20 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
 | 
				
			||||||
			} else if node.generic_types.len == 0 {
 | 
								} else if node.generic_types.len == 0 {
 | 
				
			||||||
				c.error('generic struct init must specify type parameter, e.g. Foo<T>',
 | 
									c.error('generic struct init must specify type parameter, e.g. Foo<T>',
 | 
				
			||||||
					node.pos)
 | 
										node.pos)
 | 
				
			||||||
 | 
								} else if node.generic_types.len > 0
 | 
				
			||||||
 | 
									&& node.generic_types.len != struct_sym.info.generic_types.len {
 | 
				
			||||||
 | 
									c.error('generic struct init expects $struct_sym.info.generic_types.len generic parameter, but got $node.generic_types.len',
 | 
				
			||||||
 | 
										node.pos)
 | 
				
			||||||
 | 
								} else if node.generic_types.len > 0 {
 | 
				
			||||||
 | 
									for gtyp in node.generic_types {
 | 
				
			||||||
 | 
										gtyp_name := c.table.sym(gtyp).name
 | 
				
			||||||
 | 
										if gtyp_name !in c.table.cur_fn.generic_names {
 | 
				
			||||||
 | 
											cur_generic_names := '(' + c.table.cur_fn.generic_names.join(',') + ')'
 | 
				
			||||||
 | 
											c.error('generic struct init type parameter `$gtyp_name` must be within the parameters `$cur_generic_names` of the current generic function',
 | 
				
			||||||
 | 
												node.pos)
 | 
				
			||||||
 | 
											break
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if node.generic_types.len > 0 && struct_sym.info.generic_types != node.generic_types {
 | 
							if node.generic_types.len > 0 && struct_sym.info.generic_types != node.generic_types {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.vv:6:9: error: generic struct init expects 1 generic parameter, but got 2
 | 
				
			||||||
 | 
					    4 |
 | 
				
			||||||
 | 
					    5 | pub fn send<A, B>(res A, b B) string {
 | 
				
			||||||
 | 
					    6 |     msg := Response<A, B>{
 | 
				
			||||||
 | 
					      |            ~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					    7 |         result: res
 | 
				
			||||||
 | 
					    8 |     }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					struct Response<U> {
 | 
				
			||||||
 | 
						result U
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn send<A, B>(res A, b B) string {
 | 
				
			||||||
 | 
						msg := Response<A, B>{
 | 
				
			||||||
 | 
							result: res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						println(b)
 | 
				
			||||||
 | 
						return '$msg'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						mut ret := send(123, 22.2)
 | 
				
			||||||
 | 
						println(ret)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv:6:9: error: generic struct init type parameter `U` must be within the parameters `(A,B)` of the current generic function
 | 
				
			||||||
 | 
					    4 |
 | 
				
			||||||
 | 
					    5 | pub fn send<A, B>(res A, b B) string {
 | 
				
			||||||
 | 
					    6 |     msg := Response<U>{
 | 
				
			||||||
 | 
					      |            ~~~~~~~~~~~~
 | 
				
			||||||
 | 
					    7 |         result: res
 | 
				
			||||||
 | 
					    8 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv:7:3: error: cannot assign to field `result`: expected `U`, not `int`
 | 
				
			||||||
 | 
					    5 | pub fn send<A, B>(res A, b B) string {
 | 
				
			||||||
 | 
					    6 |     msg := Response<U>{
 | 
				
			||||||
 | 
					    7 |         result: res
 | 
				
			||||||
 | 
					      |         ~~~~~~~~~~~
 | 
				
			||||||
 | 
					    8 |     }
 | 
				
			||||||
 | 
					    9 |     println(b)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					struct Response<U> {
 | 
				
			||||||
 | 
						result U
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn send<A, B>(res A, b B) string {
 | 
				
			||||||
 | 
						msg := Response<U>{
 | 
				
			||||||
 | 
							result: res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						println(b)
 | 
				
			||||||
 | 
						return '$msg'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						mut ret := send(123, 22.2)
 | 
				
			||||||
 | 
						println(ret)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue