checker: check error for generic sumtype types (#14374)
							parent
							
								
									4eb5aacd20
								
							
						
					
					
						commit
						d09c84f46f
					
				|  | @ -1166,6 +1166,7 @@ pub: | |||
| 	name          string | ||||
| 	is_pub        bool | ||||
| 	pos           token.Pos | ||||
| 	name_pos      token.Pos | ||||
| 	comments      []Comment | ||||
| 	typ           Type | ||||
| 	generic_types []Type | ||||
|  |  | |||
|  | @ -493,9 +493,26 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) { | |||
| 		} else if sym.kind == .struct_ && sym.language == .js { | ||||
| 			c.error('sum type cannot hold an JS struct', variant.pos) | ||||
| 		} else if mut sym.info is ast.Struct { | ||||
| 			if sym.info.is_generic && !variant.typ.has_flag(.generic) { | ||||
| 				c.error('generic struct `$sym.name` must specify generic type names, e.g. Foo<T>', | ||||
| 					variant.pos) | ||||
| 			if sym.info.is_generic { | ||||
| 				if !variant.typ.has_flag(.generic) { | ||||
| 					c.error('generic struct `$sym.name` must specify generic type names, e.g. Foo<T>', | ||||
| 						variant.pos) | ||||
| 				} | ||||
| 				if node.generic_types.len == 0 { | ||||
| 					c.error('generic sumtype `$node.name` must specify generic type names, e.g. Foo<T>', | ||||
| 						node.name_pos) | ||||
| 				} else { | ||||
| 					for typ in sym.info.generic_types { | ||||
| 						if typ !in node.generic_types { | ||||
| 							sumtype_type_names := node.generic_types.map(c.table.type_to_str(it)).join(', ') | ||||
| 							generic_sumtype_name := '$node.name<$sumtype_type_names>' | ||||
| 							variant_type_names := sym.info.generic_types.map(c.table.type_to_str(it)).join(', ') | ||||
| 							generic_variant_name := '$sym.name<$variant_type_names>' | ||||
| 							c.error('generic type name `${c.table.sym(typ).name}` of generic struct `$generic_variant_name` is not mentioned in sumtype `$generic_sumtype_name`', | ||||
| 								variant.pos) | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| vlib/v/checker/tests/generic_sumtype_decl_err.vv:7:24: error: generic struct `Just` must specify generic type names, e.g. Foo<T> | ||||
| vlib/v/checker/tests/generic_sumtype_decl_err_a.vv:7:24: error: generic struct `Just` must specify generic type names, e.g. Foo<T> | ||||
|     5 | struct Nothing {} | ||||
|     6 | | ||||
|     7 | type Maybe = Nothing | Just | ||||
|  | @ -0,0 +1,7 @@ | |||
| vlib/v/checker/tests/generic_sumtype_decl_err_b.vv:7:6: error: generic sumtype `Maybe` must specify generic type names, e.g. Foo<T> | ||||
|     5 | struct Nothing {} | ||||
|     6 | | ||||
|     7 | type Maybe = Nothing | Just<T> | ||||
|       |      ~~~~~ | ||||
|     8 | | ||||
|     9 | fn main() { | ||||
|  | @ -0,0 +1,10 @@ | |||
| struct Just<T> { | ||||
|   value T | ||||
| } | ||||
| 
 | ||||
| struct Nothing {} | ||||
| 
 | ||||
| type Maybe = Nothing | Just<T> | ||||
| 
 | ||||
| fn main() { | ||||
| } | ||||
|  | @ -0,0 +1,7 @@ | |||
| vlib/v/checker/tests/generic_sumtype_decl_err_c.vv:7:27: error: generic type name `T` of generic struct `Just<T>` is not mentioned in sumtype `Maybe<B>` | ||||
|     5 | struct Nothing {} | ||||
|     6 | | ||||
|     7 | type Maybe<B> = Nothing | Just<T> | ||||
|       |                           ~~~~~~~ | ||||
|     8 | | ||||
|     9 | fn main() { | ||||
|  | @ -0,0 +1,10 @@ | |||
| struct Just<T> { | ||||
|   value T | ||||
| } | ||||
| 
 | ||||
| struct Nothing {} | ||||
| 
 | ||||
| type Maybe<B> = Nothing | Just<T> | ||||
| 
 | ||||
| fn main() { | ||||
| } | ||||
|  | @ -3672,6 +3672,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { | |||
| 			generic_types: generic_types | ||||
| 			attrs: p.attrs | ||||
| 			pos: decl_pos | ||||
| 			name_pos: name_pos | ||||
| 			comments: comments | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue