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.is_public = true
 | 
				
			||||||
						typ.kind = parent.kind
 | 
											typ.kind = parent.kind
 | 
				
			||||||
						typ.methods = all_methods
 | 
											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 {
 | 
									ast.SumType {
 | 
				
			||||||
| 
						 | 
					@ -968,6 +970,8 @@ pub fn (mut c Checker) generic_insts_to_concrete() {
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						typ.is_public = true
 | 
											typ.is_public = true
 | 
				
			||||||
						typ.kind = parent.kind
 | 
											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 {}
 | 
									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{}
 | 
						return T{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct NonGenericStruct {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn use_as_generic(ngs NonGenericStruct<V>) NonGenericStruct<V> {
 | 
					 | 
				
			||||||
	return NonGenericStruct{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct GenericStruct<A, B> {}
 | 
					struct GenericStruct<A, B> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn proper_generics(gs GenericStruct<A, B>) 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 {
 | 
					pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
 | 
				
			||||||
	mut bs_name := name
 | 
						mut bs_name := name
 | 
				
			||||||
	mut bs_cname := name
 | 
						mut bs_cname := name
 | 
				
			||||||
 | 
						start_pos := p.tok.position()
 | 
				
			||||||
	p.next()
 | 
						p.next()
 | 
				
			||||||
	p.in_generic_params = true
 | 
						p.in_generic_params = true
 | 
				
			||||||
	bs_name += '<'
 | 
						bs_name += '<'
 | 
				
			||||||
| 
						 | 
					@ -561,6 +562,7 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
 | 
				
			||||||
		bs_name += ', '
 | 
							bs_name += ', '
 | 
				
			||||||
		bs_cname += '_'
 | 
							bs_cname += '_'
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						concrete_types_pos := start_pos.extend(p.tok.position())
 | 
				
			||||||
	p.check(.gt)
 | 
						p.check(.gt)
 | 
				
			||||||
	p.in_generic_params = false
 | 
						p.in_generic_params = false
 | 
				
			||||||
	bs_name += '>'
 | 
						bs_name += '>'
 | 
				
			||||||
| 
						 | 
					@ -575,6 +577,38 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
 | 
				
			||||||
		if parent_idx == 0 {
 | 
							if parent_idx == 0 {
 | 
				
			||||||
			parent_idx = p.table.add_placeholder_type(name, .v)
 | 
								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{
 | 
							idx := p.table.register_type_symbol(ast.TypeSymbol{
 | 
				
			||||||
			kind: .generic_inst
 | 
								kind: .generic_inst
 | 
				
			||||||
			name: bs_name
 | 
								name: bs_name
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue