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