checker: check error for generic sumtype types (#14374)

master
yuyi 2022-05-12 16:57:57 +08:00 committed by GitHub
parent e93a8766e5
commit f48f7014f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 57 additions and 4 deletions

View File

@ -1166,6 +1166,7 @@ pub:
name string
is_pub bool
pos token.Pos
name_pos token.Pos
comments []Comment
typ Type
generic_types []Type

View File

@ -493,10 +493,27 @@ 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) {
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)
}
}
}
}
}
if sym.name.trim_string_left(sym.mod + '.') == node.name {

View File

@ -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

View File

@ -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() {

View File

@ -0,0 +1,10 @@
struct Just<T> {
value T
}
struct Nothing {}
type Maybe = Nothing | Just<T>
fn main() {
}

View File

@ -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() {

View File

@ -0,0 +1,10 @@
struct Just<T> {
value T
}
struct Nothing {}
type Maybe<B> = Nothing | Just<T>
fn main() {
}

View File

@ -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
}
}