1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: add error for type Alias = map[string]Alias (fix #17008) (#17015)

This commit is contained in:
Delyan Angelov 2023-01-18 01:34:43 +02:00 committed by GitHub
parent 88dab8fc2d
commit 1cad788779
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 21 deletions

View File

@ -784,8 +784,9 @@ fn (t Tree) alias_type_decl(node ast.AliasTypeDecl) &Node {
mut obj := new_object()
obj.add_terse('ast_type', t.string_node('AliasTypeDecl'))
obj.add_terse('name', t.string_node(node.name))
obj.add_terse('is_pub', t.bool_node(node.is_pub))
obj.add_terse('typ', t.type_node(node.typ))
obj.add_terse('parent_type', t.type_node(node.parent_type))
obj.add_terse('is_pub', t.bool_node(node.is_pub))
obj.add('comments', t.array_node_comment(node.comments))
obj.add('pos', t.pos(node.pos))
return obj

View File

@ -1183,6 +1183,7 @@ pub struct AliasTypeDecl {
pub:
name string
is_pub bool
typ Type
parent_type Type
pos token.Pos
type_pos token.Pos

View File

@ -435,32 +435,88 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) {
c.check_valid_pascal_case(node.name, 'type alias', node.pos)
}
c.ensure_type_exists(node.parent_type, node.type_pos) or { return }
mut typ_sym := c.table.sym(node.parent_type)
if typ_sym.kind in [.placeholder, .int_literal, .float_literal] {
c.error('unknown type `${typ_sym.name}`', node.type_pos)
} else if typ_sym.kind == .alias {
orig_sym := c.table.sym((typ_sym.info as ast.Alias).parent_type)
c.error('type `${typ_sym.str()}` is an alias, use the original alias type `${orig_sym.name}` instead',
node.type_pos)
} else if typ_sym.kind == .chan {
c.error('aliases of `chan` types are not allowed.', node.type_pos)
} else if typ_sym.kind == .function {
orig_sym := c.table.type_to_str(node.parent_type)
c.error('type `${typ_sym.str()}` is an alias, use the original alias type `${orig_sym}` instead',
node.type_pos)
} else if typ_sym.kind == .struct_ {
if mut typ_sym.info is ast.Struct {
// check if the generic param types have been defined
for ct in typ_sym.info.concrete_types {
ct_sym := c.table.sym(ct)
if ct_sym.kind == .placeholder {
c.error('unknown type `${ct_sym.name}`', node.type_pos)
mut parent_typ_sym := c.table.sym(node.parent_type)
match parent_typ_sym.kind {
.placeholder, .int_literal, .float_literal {
c.error('unknown aliased type `${parent_typ_sym.name}`', node.type_pos)
}
.alias {
orig_sym := c.table.sym((parent_typ_sym.info as ast.Alias).parent_type)
c.error('type `${parent_typ_sym.str()}` is an alias, use the original alias type `${orig_sym.name}` instead',
node.type_pos)
}
.chan {
c.error('aliases of `chan` types are not allowed', node.type_pos)
}
.thread {
c.error('aliases of `thread` types are not allowed', node.type_pos)
}
.multi_return {
c.error('aliases of function multi return types are not allowed', node.type_pos)
}
.void {
c.error('aliases of the void type are not allowed', node.type_pos)
}
.function {
orig_sym := c.table.type_to_str(node.parent_type)
c.error('type `${parent_typ_sym.str()}` is an alias, use the original alias type `${orig_sym}` instead',
node.type_pos)
}
.struct_ {
if mut parent_typ_sym.info is ast.Struct {
// check if the generic param types have been defined
for ct in parent_typ_sym.info.concrete_types {
ct_sym := c.table.sym(ct)
if ct_sym.kind == .placeholder {
c.error('unknown type `${ct_sym.name}`', node.type_pos)
}
}
}
}
.array {
c.check_alias_vs_element_type_of_parent(node, (parent_typ_sym.info as ast.Array).elem_type,
'array')
}
.array_fixed {
c.check_alias_vs_element_type_of_parent(node, (parent_typ_sym.info as ast.ArrayFixed).elem_type,
'fixed array')
}
.map {
info := parent_typ_sym.info as ast.Map
c.check_alias_vs_element_type_of_parent(node, info.key_type, 'map key')
c.check_alias_vs_element_type_of_parent(node, info.value_type, 'map value')
}
.sum_type {
// TODO: decide whether the following should be allowed. Note that it currently works,
// while `type Sum = int | Sum` is explicitly disallowed:
// type Sum = int | Alias
// type Alias = Sum
}
// The rest of the parent symbol kinds are also allowed, since they are either primitive types,
// that in turn do not allow recursion, or are abstract enough so that they can not be checked at comptime:
else {}
/*
.voidptr, .byteptr, .charptr {}
.char, .rune, .bool {}
.string, .enum_, .none_, .any {}
.i8, .i16, .int, .i64, .isize {}
.u8, .u16, .u32, .u64, .usize {}
.f32, .f64 {}
.interface_ {}
.generic_inst {}
.aggregate {}
*/
}
}
fn (mut c Checker) check_alias_vs_element_type_of_parent(node ast.AliasTypeDecl, element_type_of_parent ast.Type, label string) {
if node.typ.idx() != element_type_of_parent.idx() {
return
}
c.error('recursive declarations of aliases are not allowed - the alias `${node.name}` is used in the ${label}',
node.type_pos)
}
fn (mut c Checker) fn_type_decl(node ast.FnTypeDecl) {
c.check_valid_pascal_case(node.name, 'fn type', node.pos)
typ_sym := c.table.sym(node.typ)
@ -4230,6 +4286,12 @@ fn (mut c Checker) ensure_generic_type_specify_type_names(typ ast.Type, pos toke
}
sym := c.table.final_sym(typ)
if c.ensure_generic_type_level > 38 {
dump(typ)
dump(sym.kind)
dump(pos)
dump(c.ensure_generic_type_level)
}
match sym.kind {
.function {
fn_info := sym.info as ast.FnType

View File

@ -0,0 +1,50 @@
vlib/v/checker/tests/recursive_alias_type_err.vv:1:24: error: recursive declarations of aliases are not allowed - the alias `VTableTypeArray` is used in the array
1 | type VTableTypeArray = []VTableTypeArray
| ~~~~~~~~~~~~~~~~~
2 | type VTableTypeArrayPointer = []&VTableTypeArrayPointer
3 |
vlib/v/checker/tests/recursive_alias_type_err.vv:2:31: error: recursive declarations of aliases are not allowed - the alias `VTableTypeArrayPointer` is used in the array
1 | type VTableTypeArray = []VTableTypeArray
2 | type VTableTypeArrayPointer = []&VTableTypeArrayPointer
| ~~~~~~~~~~~~~~~~~~~~~~~~~
3 |
4 | type VTableTypeArrayFixed = [5]VTableTypeArrayFixed
vlib/v/checker/tests/recursive_alias_type_err.vv:4:29: error: recursive declarations of aliases are not allowed - the alias `VTableTypeArrayFixed` is used in the fixed array
2 | type VTableTypeArrayPointer = []&VTableTypeArrayPointer
3 |
4 | type VTableTypeArrayFixed = [5]VTableTypeArrayFixed
| ~~~~~~~~~~~~~~~~~~~~~~~
5 | type VTableTypeArrayFixedPointer = [5]&VTableTypeArrayFixedPointer
6 |
vlib/v/checker/tests/recursive_alias_type_err.vv:5:36: error: recursive declarations of aliases are not allowed - the alias `VTableTypeArrayFixedPointer` is used in the fixed array
3 |
4 | type VTableTypeArrayFixed = [5]VTableTypeArrayFixed
5 | type VTableTypeArrayFixedPointer = [5]&VTableTypeArrayFixedPointer
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | type VTableTypeMap = map[string]VTableTypeMap
vlib/v/checker/tests/recursive_alias_type_err.vv:7:22: error: recursive declarations of aliases are not allowed - the alias `VTableTypeMap` is used in the map value
5 | type VTableTypeArrayFixedPointer = [5]&VTableTypeArrayFixedPointer
6 |
7 | type VTableTypeMap = map[string]VTableTypeMap
| ~~~~~~~~~~~~~~~~~~~~~~~~
8 | type VTableTypeMapOfPointer = map[string]&VTableTypeMapOfPointer
9 |
vlib/v/checker/tests/recursive_alias_type_err.vv:8:31: error: recursive declarations of aliases are not allowed - the alias `VTableTypeMapOfPointer` is used in the map value
6 |
7 | type VTableTypeMap = map[string]VTableTypeMap
8 | type VTableTypeMapOfPointer = map[string]&VTableTypeMapOfPointer
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 |
10 | type VTableTypeMapKey = map[VTableTypeMapKey]int
vlib/v/checker/tests/recursive_alias_type_err.vv:10:25: error: recursive declarations of aliases are not allowed - the alias `VTableTypeMapKey` is used in the map key
8 | type VTableTypeMapOfPointer = map[string]&VTableTypeMapOfPointer
9 |
10 | type VTableTypeMapKey = map[VTableTypeMapKey]int
| ~~~~~~~~~~~~~~~~~~~~~~~~
11 | type VTableTypeMapOfPointerKey = map[&VTableTypeMapOfPointerKey]int
vlib/v/checker/tests/recursive_alias_type_err.vv:11:34: error: recursive declarations of aliases are not allowed - the alias `VTableTypeMapOfPointerKey` is used in the map key
9 |
10 | type VTableTypeMapKey = map[VTableTypeMapKey]int
11 | type VTableTypeMapOfPointerKey = map[&VTableTypeMapOfPointerKey]int
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,11 @@
type VTableTypeArray = []VTableTypeArray
type VTableTypeArrayPointer = []&VTableTypeArrayPointer
type VTableTypeArrayFixed = [5]VTableTypeArrayFixed
type VTableTypeArrayFixedPointer = [5]&VTableTypeArrayFixedPointer
type VTableTypeMap = map[string]VTableTypeMap
type VTableTypeMapOfPointer = map[string]&VTableTypeMapOfPointer
type VTableTypeMapKey = map[VTableTypeMapKey]int
type VTableTypeMapOfPointerKey = map[&VTableTypeMapOfPointerKey]int

View File

@ -4000,6 +4000,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
return ast.AliasTypeDecl{
name: name
is_pub: is_pub
typ: idx
parent_type: parent_type
type_pos: type_pos.extend(type_end_pos)
pos: decl_pos