From 5c0617591fcacf06c95c60f11977cf9eefc09557 Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+ttytm@users.noreply.github.com> Date: Sat, 30 Mar 2024 12:10:29 +0100 Subject: [PATCH] parser, checker: move error handling for user defined type duplicates to the checker to resolve parsing issues (#21147) --- vlib/v/checker/checker.v | 11 ++++++++ vlib/v/checker/tests/alias_type_exists.out | 3 -- vlib/v/checker/tests/alias_type_unkown.out | 3 ++ ...as_type_exists.vv => alias_type_unkown.vv} | 0 vlib/v/checker/tests/type_exists_err.out | 28 +++++++++++++++++++ vlib/v/checker/tests/type_exists_err.vv | 11 ++++++++ vlib/v/fmt/fmt.v | 2 +- vlib/v/parser/parser.v | 12 ++++---- vlib/v/parser/tests/sum_type_exists_err.out | 4 +-- .../tests/type_alias_existing_type_err.out | 7 ----- .../tests/type_alias_existing_type_err.vv | 7 ----- 11 files changed, 62 insertions(+), 26 deletions(-) delete mode 100644 vlib/v/checker/tests/alias_type_exists.out create mode 100644 vlib/v/checker/tests/alias_type_unkown.out rename vlib/v/checker/tests/{alias_type_exists.vv => alias_type_unkown.vv} (100%) create mode 100644 vlib/v/checker/tests/type_exists_err.out create mode 100644 vlib/v/checker/tests/type_exists_err.vv delete mode 100644 vlib/v/parser/tests/type_alias_existing_type_err.out delete mode 100644 vlib/v/parser/tests/type_alias_existing_type_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 93d53c494..86c551109 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -499,6 +499,12 @@ fn (mut c Checker) check_valid_pascal_case(name string, identifier string, pos t } fn (mut c Checker) type_decl(node ast.TypeDecl) { + if node.typ == ast.invalid_type_idx && (node is ast.AliasTypeDecl || node is ast.SumTypeDecl) { + typ_desc := if node is ast.AliasTypeDecl { 'alias' } else { 'sum type' } + c.error('cannot register ${typ_desc} `${node.name}`, another type with this name exists', + node.pos) + return + } match node { ast.AliasTypeDecl { c.alias_type_decl(node) } ast.FnTypeDecl { c.fn_type_decl(node) } @@ -1788,6 +1794,11 @@ fn (mut c Checker) const_decl(mut node ast.ConstDecl) { fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { c.check_valid_pascal_case(node.name, 'enum name', node.pos) + if node.typ == ast.invalid_type_idx { + c.error('cannot register enum `${node.name}`, another type with this name exists', + node.pos) + return + } mut useen := []u64{} mut iseen := []i64{} mut seen_enum_field_names := map[string]int{} diff --git a/vlib/v/checker/tests/alias_type_exists.out b/vlib/v/checker/tests/alias_type_exists.out deleted file mode 100644 index d79df8a33..000000000 --- a/vlib/v/checker/tests/alias_type_exists.out +++ /dev/null @@ -1,3 +0,0 @@ -vlib/v/checker/tests/alias_type_exists.vv:1:15: error: unknown type `Bird` - 1 | type Pigeon = Bird - | ~~~~ \ No newline at end of file diff --git a/vlib/v/checker/tests/alias_type_unkown.out b/vlib/v/checker/tests/alias_type_unkown.out new file mode 100644 index 000000000..180169c9a --- /dev/null +++ b/vlib/v/checker/tests/alias_type_unkown.out @@ -0,0 +1,3 @@ +vlib/v/checker/tests/alias_type_unkown.vv:1:15: error: unknown type `Bird` + 1 | type Pigeon = Bird + | ~~~~ diff --git a/vlib/v/checker/tests/alias_type_exists.vv b/vlib/v/checker/tests/alias_type_unkown.vv similarity index 100% rename from vlib/v/checker/tests/alias_type_exists.vv rename to vlib/v/checker/tests/alias_type_unkown.vv diff --git a/vlib/v/checker/tests/type_exists_err.out b/vlib/v/checker/tests/type_exists_err.out new file mode 100644 index 000000000..adbb71b72 --- /dev/null +++ b/vlib/v/checker/tests/type_exists_err.out @@ -0,0 +1,28 @@ +vlib/v/checker/tests/type_exists_err.vv:3:1: error: cannot register alias `Foo`, another type with this name exists + 1 | struct Foo {} + 2 | + 3 | type Foo = Foo + | ~~~~~~~~ + 4 | + 5 | type Foo = string +vlib/v/checker/tests/type_exists_err.vv:5:1: error: cannot register alias `Foo`, another type with this name exists + 3 | type Foo = Foo + 4 | + 5 | type Foo = string + | ~~~~~~~~ + 6 | + 7 | type Foo = int | string +vlib/v/checker/tests/type_exists_err.vv:7:1: error: cannot register sum type `Foo`, another type with this name exists + 5 | type Foo = string + 6 | + 7 | type Foo = int | string + | ~~~~~~~~ + 8 | + 9 | enum Foo { +vlib/v/checker/tests/type_exists_err.vv:9:1: error: cannot register enum `Foo`, another type with this name exists + 7 | type Foo = int | string + 8 | + 9 | enum Foo { + | ~~~~~~~~ + 10 | @none + 11 | } diff --git a/vlib/v/checker/tests/type_exists_err.vv b/vlib/v/checker/tests/type_exists_err.vv new file mode 100644 index 000000000..109901a79 --- /dev/null +++ b/vlib/v/checker/tests/type_exists_err.vv @@ -0,0 +1,11 @@ +struct Foo {} + +type Foo = Foo + +type Foo = string + +type Foo = int | string + +enum Foo { + @none +} diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index b13728c1a..fa57e50df 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1002,7 +1002,7 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) { f.write('pub ') } mut name := node.name.after('.') - if node.typ != ast.int_type { + if node.typ != ast.int_type && node.typ != ast.invalid_type_idx { senum_type := f.table.type_to_str_using_aliases(node.typ, f.mod2alias) name += ' as ${senum_type}' } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 9981d50bb..0af88768c 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -4296,11 +4296,13 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { } is_pub: is_pub }) - if idx in [ast.invalid_type_idx, ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, - ast.map_type_idx] { + if idx in [ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, ast.map_type_idx] { p.error_with_pos('cannot register enum `${name}`, another type with this name exists', end_pos) } + if idx == ast.invalid_type_idx { + enum_type = idx + } enum_decl := ast.EnumDecl{ name: name @@ -4402,8 +4404,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { } is_pub: is_pub }) - if typ in [ast.invalid_type_idx, ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, - ast.map_type_idx] { + if typ in [ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, ast.map_type_idx] { p.error_with_pos('cannot register sum type `${name}`, another type with this name exists', name_pos) return ast.SumTypeDecl{} @@ -4443,8 +4444,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { is_pub: is_pub }) type_end_pos := p.prev_tok.pos() - if idx in [ast.invalid_type_idx, ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, - ast.map_type_idx] { + if idx in [ast.string_type_idx, ast.rune_type_idx, ast.array_type_idx, ast.map_type_idx] { p.error_with_pos('cannot register alias `${name}`, another type with this name exists', name_pos) return ast.AliasTypeDecl{} diff --git a/vlib/v/parser/tests/sum_type_exists_err.out b/vlib/v/parser/tests/sum_type_exists_err.out index 99bbeafa8..3206de3b1 100644 --- a/vlib/v/parser/tests/sum_type_exists_err.out +++ b/vlib/v/parser/tests/sum_type_exists_err.out @@ -1,3 +1,3 @@ -vlib/v/parser/tests/sum_type_exists_err.vv:1:6: error: cannot register sum type `Option`, another type with this name exists +vlib/v/parser/tests/sum_type_exists_err.vv:1:1: error: cannot register sum type `Option`, another type with this name exists 1 | type Option = string | int - | ~~~~~~ + | ~~~~~~~~~~~ diff --git a/vlib/v/parser/tests/type_alias_existing_type_err.out b/vlib/v/parser/tests/type_alias_existing_type_err.out deleted file mode 100644 index e3ada576e..000000000 --- a/vlib/v/parser/tests/type_alias_existing_type_err.out +++ /dev/null @@ -1,7 +0,0 @@ -vlib/v/parser/tests/type_alias_existing_type_err.vv:3:6: error: cannot register alias `Foo`, another type with this name exists - 1 | struct Foo{} - 2 | - 3 | type Foo = Foo - | ~~~ - 4 | - 5 | fn main() { diff --git a/vlib/v/parser/tests/type_alias_existing_type_err.vv b/vlib/v/parser/tests/type_alias_existing_type_err.vv deleted file mode 100644 index c1aeeed29..000000000 --- a/vlib/v/parser/tests/type_alias_existing_type_err.vv +++ /dev/null @@ -1,7 +0,0 @@ -struct Foo{} - -type Foo = Foo - -fn main() { - -} -- 2.39.5