parser, checker: optimize checking generic struct type mismatch (#12179)
							parent
							
								
									4490d5ed29
								
							
						
					
					
						commit
						c9b2f878b3
					
				|  | @ -932,6 +932,8 @@ pub fn (mut c Checker) generic_insts_to_concrete() { | |||
| 						typ.is_public = true | ||||
| 						typ.kind = parent.kind | ||||
| 						typ.methods = all_methods | ||||
| 					} else { | ||||
| 						util.verror('generic error', 'the number of generic types of interface `$parent.name` is inconsistent with the concrete types') | ||||
| 					} | ||||
| 				} | ||||
| 				ast.SumType { | ||||
|  | @ -968,6 +970,8 @@ pub fn (mut c Checker) generic_insts_to_concrete() { | |||
| 						} | ||||
| 						typ.is_public = true | ||||
| 						typ.kind = parent.kind | ||||
| 					} else { | ||||
| 						util.verror('generic error', 'the number of generic types of sumtype `$parent.name` is inconsistent with the concrete types') | ||||
| 					} | ||||
| 				} | ||||
| 				else {} | ||||
|  |  | |||
|  | @ -1 +1,6 @@ | |||
| generic error: struct `main.Test` is not a generic struct, cannot instantiate to the concrete types | ||||
| vlib/v/checker/tests/generics_inst_non_generic_struct_err.vv:5:14: error: struct `Test` is not a generic struct, cannot instantiate to the concrete types | ||||
|     3 | | ||||
|     4 | fn main() { | ||||
|     5 |     println(Test<string>{}) | ||||
|       |                 ~~~~~~~~ | ||||
|     6 | } | ||||
|  |  | |||
|  | @ -1 +1,7 @@ | |||
| generic error: the number of generic types of struct `main.Example` is inconsistent with the concrete types | ||||
| vlib/v/checker/tests/generics_struct_type_mismatch_err.vv:7:20: error: the number of generic types of struct `Example` is inconsistent with the concrete types | ||||
|     5 | | ||||
|     6 | fn main() { | ||||
|     7 |     example := Example<string>{ | ||||
|       |                       ~~~~~~~~ | ||||
|     8 |         key: 'key' | ||||
|     9 |         value: 'value' | ||||
|  |  | |||
|  | @ -14,12 +14,6 @@ fn (_ Foo) simple<T>() T { | |||
| 	return T{} | ||||
| } | ||||
| 
 | ||||
| struct NonGenericStruct {} | ||||
| 
 | ||||
| fn use_as_generic(ngs NonGenericStruct<V>) NonGenericStruct<V> { | ||||
| 	return NonGenericStruct{} | ||||
| } | ||||
| 
 | ||||
| struct GenericStruct<A, B> {} | ||||
| 
 | ||||
| fn proper_generics(gs GenericStruct<A, B>) GenericStruct<A, B> { | ||||
|  |  | |||
|  | @ -539,6 +539,7 @@ pub fn (mut p Parser) parse_generic_type(name string) ast.Type { | |||
| pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type { | ||||
| 	mut bs_name := name | ||||
| 	mut bs_cname := name | ||||
| 	start_pos := p.tok.position() | ||||
| 	p.next() | ||||
| 	p.in_generic_params = true | ||||
| 	bs_name += '<' | ||||
|  | @ -561,6 +562,7 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type { | |||
| 		bs_name += ', ' | ||||
| 		bs_cname += '_' | ||||
| 	} | ||||
| 	concrete_types_pos := start_pos.extend(p.tok.position()) | ||||
| 	p.check(.gt) | ||||
| 	p.in_generic_params = false | ||||
| 	bs_name += '>' | ||||
|  | @ -575,6 +577,38 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type { | |||
| 		if parent_idx == 0 { | ||||
| 			parent_idx = p.table.add_placeholder_type(name, .v) | ||||
| 		} | ||||
| 		parent_sym := p.table.get_type_symbol(ast.new_type(parent_idx)) | ||||
| 		match parent_sym.info { | ||||
| 			ast.Struct { | ||||
| 				if parent_sym.info.generic_types.len == 0 { | ||||
| 					p.error_with_pos('struct `$parent_sym.name` is not a generic struct, cannot instantiate to the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} else if parent_sym.info.generic_types.len != concrete_types.len { | ||||
| 					p.error_with_pos('the number of generic types of struct `$parent_sym.name` is inconsistent with the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} | ||||
| 			} | ||||
| 			ast.Interface { | ||||
| 				if parent_sym.info.generic_types.len == 0 { | ||||
| 					p.error_with_pos('interface `$parent_sym.name` is not a generic interface, cannot instantiate to the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} else if parent_sym.info.generic_types.len != concrete_types.len { | ||||
| 					p.error_with_pos('the number of generic types of interfce `$parent_sym.name` is inconsistent with the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} | ||||
| 			} | ||||
| 			ast.SumType { | ||||
| 				if parent_sym.info.generic_types.len == 0 { | ||||
| 					p.error_with_pos('sumtype `$parent_sym.name` is not a generic sumtype, cannot instantiate to the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} else if parent_sym.info.generic_types.len != concrete_types.len { | ||||
| 					p.error_with_pos('the number of generic types of sumtype `$parent_sym.name` is inconsistent with the concrete types', | ||||
| 						concrete_types_pos) | ||||
| 				} | ||||
| 			} | ||||
| 			else {} | ||||
| 		} | ||||
| 
 | ||||
| 		idx := p.table.register_type_symbol(ast.TypeSymbol{ | ||||
| 			kind: .generic_inst | ||||
| 			name: bs_name | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue