checker: fix position of unknown type errors (#10110)
parent
ed6ad728d9
commit
0d44c8857e
|
@ -572,6 +572,9 @@ pub fn (t &Table) known_type_idx(typ Type) bool {
|
|||
.array {
|
||||
return t.known_type_idx((sym.info as Array).elem_type)
|
||||
}
|
||||
.array_fixed {
|
||||
return t.known_type_idx((sym.info as ArrayFixed).elem_type)
|
||||
}
|
||||
.map {
|
||||
info := sym.info as Map
|
||||
return t.known_type_idx(info.key_type) && t.known_type_idx(info.value_type)
|
||||
|
@ -965,7 +968,8 @@ pub fn (t &Table) known_type_names() []string {
|
|||
mut res := []string{cap: t.type_idxs.len}
|
||||
for _, idx in t.type_idxs {
|
||||
// Skip `int_literal_type_idx` and `float_literal_type_idx` because they shouldn't be visible to the User.
|
||||
if idx !in [0, int_literal_type_idx, float_literal_type_idx] && t.known_type_idx(idx) {
|
||||
if idx !in [0, int_literal_type_idx, float_literal_type_idx] && t.known_type_idx(idx)
|
||||
&& t.get_type_symbol(idx).kind != .function {
|
||||
res << t.type_to_str(idx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -309,18 +309,19 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
|
|||
|
||||
pub fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) {
|
||||
// TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available
|
||||
if c.file.mod.name != 'time' && c.file.mod.name != 'builtin' {
|
||||
if c.file.mod.name !in ['time', 'builtin'] {
|
||||
c.check_valid_pascal_case(node.name, 'type alias', node.pos)
|
||||
}
|
||||
c.ensure_type_exists(node.parent_type, node.type_pos) or { return }
|
||||
typ_sym := c.table.get_type_symbol(node.parent_type)
|
||||
if typ_sym.kind in [.placeholder, .int_literal, .float_literal] {
|
||||
c.error("type `$typ_sym.name` doesn't exist", node.pos)
|
||||
c.error('unknown type `$typ_sym.name`', node.type_pos)
|
||||
} else if typ_sym.kind == .alias {
|
||||
orig_sym := c.table.get_type_symbol((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.pos)
|
||||
node.type_pos)
|
||||
} else if typ_sym.kind == .chan {
|
||||
c.error('aliases of `chan` types are not allowed.', node.pos)
|
||||
c.error('aliases of `chan` types are not allowed.', node.type_pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,14 +330,16 @@ pub fn (mut c Checker) fn_type_decl(node ast.FnTypeDecl) {
|
|||
typ_sym := c.table.get_type_symbol(node.typ)
|
||||
fn_typ_info := typ_sym.info as ast.FnType
|
||||
fn_info := fn_typ_info.func
|
||||
c.ensure_type_exists(fn_info.return_type, fn_info.return_type_pos) or {}
|
||||
ret_sym := c.table.get_type_symbol(fn_info.return_type)
|
||||
if ret_sym.kind == .placeholder {
|
||||
c.error("type `$ret_sym.name` doesn't exist", node.pos)
|
||||
c.error('unknown type `$ret_sym.name`', fn_info.return_type_pos)
|
||||
}
|
||||
for arg in fn_info.params {
|
||||
c.ensure_type_exists(arg.typ, arg.type_pos) or { return }
|
||||
arg_sym := c.table.get_type_symbol(arg.typ)
|
||||
if arg_sym.kind == .placeholder {
|
||||
c.error("type `$arg_sym.name` doesn't exist", node.pos)
|
||||
c.error('unknown type `$arg_sym.name`', arg.type_pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,12 +351,13 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) {
|
|||
if variant.typ.is_ptr() {
|
||||
c.error('sum type cannot hold a reference type', variant.pos)
|
||||
}
|
||||
c.ensure_type_exists(variant.typ, variant.pos) or {}
|
||||
mut sym := c.table.get_type_symbol(variant.typ)
|
||||
if sym.name in names_used {
|
||||
c.error('sum type $node.name cannot hold the type `$sym.name` more than once',
|
||||
variant.pos)
|
||||
} else if sym.kind in [.placeholder, .int_literal, .float_literal] {
|
||||
c.error("type `$sym.name` doesn't exist", variant.pos)
|
||||
c.error('unknown type `$sym.name`', variant.pos)
|
||||
} else if sym.kind == .interface_ {
|
||||
c.error('sum type cannot hold an interface', variant.pos)
|
||||
}
|
||||
|
@ -7017,7 +7021,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
if node.language == .v {
|
||||
// Make sure all types are valid
|
||||
for arg in node.params {
|
||||
c.ensure_type_exists(arg.typ, node.pos) or { return }
|
||||
c.ensure_type_exists(arg.typ, arg.type_pos) or { return }
|
||||
}
|
||||
}
|
||||
if node.language == .v && node.name.after_char(`.`) == 'init' && !node.is_method
|
||||
|
@ -7030,7 +7034,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
}
|
||||
}
|
||||
if node.return_type != ast.Type(0) {
|
||||
c.ensure_type_exists(node.return_type, node.pos) or { return }
|
||||
c.ensure_type_exists(node.return_type, node.return_type_pos) or { return }
|
||||
if node.language == .v && node.is_method && node.name == 'str' {
|
||||
if node.return_type != ast.string_type {
|
||||
c.error('.str() methods should return `string`', node.pos)
|
||||
|
@ -7214,6 +7218,9 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Position) ? {
|
|||
.array {
|
||||
c.ensure_type_exists((sym.info as ast.Array).elem_type, pos) ?
|
||||
}
|
||||
.array_fixed {
|
||||
c.ensure_type_exists((sym.info as ast.ArrayFixed).elem_type, pos) ?
|
||||
}
|
||||
.map {
|
||||
info := sym.info as ast.Map
|
||||
c.ensure_type_exists(info.key_type, pos) ?
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
vlib/v/checker/tests/alias_type_exists.vv:1:1: error: type `Bird` doesn't exist
|
||||
vlib/v/checker/tests/alias_type_exists.vv:1:15: error: unknown type `Bird`
|
||||
1 | type Pigeon = Bird
|
||||
| ~~~~~~~~~~~
|
||||
2 |
|
||||
3 | fn main() {
|
||||
| ~~~~
|
|
@ -1,5 +1 @@
|
|||
type Pigeon = Bird
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
vlib/v/checker/tests/any_int_float_ban_err.vv:1:12: error: type `int_literal` doesn't exist
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:1:12: error: unknown type `int_literal`
|
||||
1 | type Foo = int_literal | float_literal
|
||||
| ~~~~~~~~~~~
|
||||
2 | type Fo2 = int_literal
|
||||
3 |
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:2:1: error: type `int_literal` doesn't exist
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:2:12: error: unknown type `int_literal`
|
||||
1 | type Foo = int_literal | float_literal
|
||||
2 | type Fo2 = int_literal
|
||||
| ~~~~~~~~
|
||||
| ~~~~~~~~~~~
|
||||
3 |
|
||||
4 | struct Int {
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:5:7: error: unknown type `int_literal`
|
||||
|
@ -23,18 +23,18 @@ vlib/v/checker/tests/any_int_float_ban_err.vv:6:7: error: unknown type `float_li
|
|||
| ~~~~~~~~~~~~~
|
||||
7 | }
|
||||
8 |
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:9:1: error: unknown type `int_literal`
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:9:10: error: unknown type `int_literal`
|
||||
7 | }
|
||||
8 |
|
||||
9 | fn foo(i int_literal) int_literal {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| ~~~~~~~~~~~
|
||||
10 | return i
|
||||
11 | }
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:13:1: error: unknown type `int_literal`
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:13:11: error: unknown type `int_literal`
|
||||
11 | }
|
||||
12 |
|
||||
13 | fn foo2() int_literal {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
| ~~~~~~~~~~~
|
||||
14 | return 1
|
||||
15 | }
|
||||
vlib/v/checker/tests/any_int_float_ban_err.vv:14:12: error: cannot use `int literal` as type `int_literal` in return argument
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
vlib/v/checker/tests/const_array_unknown_type_err.vv:1:11: error: unknown type `BB`.
|
||||
Did you mean `AA`?
|
||||
1 | type AA = [20]BB
|
||||
| ~~~~~~
|
|
@ -0,0 +1 @@
|
|||
type AA = [20]BB
|
|
@ -1,12 +1,10 @@
|
|||
vlib/v/checker/tests/fn_type_exists.vv:1:1: error: type `Pants` doesn't exist
|
||||
vlib/v/checker/tests/fn_type_exists.vv:1:34: error: unknown type `Pants`
|
||||
1 | type PantsCreator = fn (a Shirt) Pants
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
| ~~~~~
|
||||
2 |
|
||||
3 | type PantsConsumer = fn (p Pants)
|
||||
vlib/v/checker/tests/fn_type_exists.vv:3:1: error: type `Pants` doesn't exist
|
||||
vlib/v/checker/tests/fn_type_exists.vv:3:28: error: unknown type `Pants`
|
||||
1 | type PantsCreator = fn (a Shirt) Pants
|
||||
2 |
|
||||
3 | type PantsConsumer = fn (p Pants)
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
4 |
|
||||
5 | fn main() {
|
||||
| ~~~~~
|
|
@ -1,7 +1,3 @@
|
|||
type PantsCreator = fn (a Shirt) Pants
|
||||
|
||||
type PantsConsumer = fn (p Pants)
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/nested_aliases.vv:2:1: error: type `MyInt` is an alias, use the original alias type `int` instead
|
||||
vlib/v/checker/tests/nested_aliases.vv:2:16: error: type `MyInt` is an alias, use the original alias type `int` instead
|
||||
1 | type MyInt = int
|
||||
2 | type MyMyInt = MyInt
|
||||
| ~~~~~~~~~~~~
|
||||
| ~~~~~
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/receiver_unknown_type_single_letter.vv:1:1: error: unknown type `Abc`
|
||||
vlib/v/checker/tests/receiver_unknown_type_single_letter.vv:1:7: error: unknown type `Abc`
|
||||
1 | fn (p Abc) foo() {}
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
| ~~~
|
||||
2 |
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
vlib/v/checker/tests/sum_type_exists.vv:1:22: error: type `Nope` doesn't exist
|
||||
1 | type Miscellaneous = Nope | Inexistant | int
|
||||
| ~~~~
|
||||
2 |
|
||||
3 | fn main() {
|
||||
vlib/v/checker/tests/sum_type_exists.vv:1:22: error: unknown type `Inexistant`
|
||||
1 | type Miscellaneous = Inexistant | Nope | int
|
||||
| ~~~~~~~~~~
|
|
@ -1,5 +1 @@
|
|||
type Miscellaneous = Nope | Inexistant | int
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
type Miscellaneous = Inexistant | Nope | int
|
||||
|
|
|
@ -5,6 +5,7 @@ module parser
|
|||
|
||||
import v.ast
|
||||
import v.util
|
||||
import v.token
|
||||
|
||||
pub fn (mut p Parser) parse_array_type() ast.Type {
|
||||
p.check(.lsbr)
|
||||
|
@ -203,17 +204,21 @@ pub fn (mut p Parser) parse_fn_type(name string) ast.Type {
|
|||
}
|
||||
}
|
||||
mut return_type := ast.void_type
|
||||
mut return_type_pos := token.Position{}
|
||||
if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() {
|
||||
return_type_pos = p.tok.position()
|
||||
return_type = p.parse_type()
|
||||
if return_type.has_flag(.generic) {
|
||||
has_generic = true
|
||||
}
|
||||
return_type_pos = return_type_pos.extend(p.prev_tok.position())
|
||||
}
|
||||
func := ast.Fn{
|
||||
name: name
|
||||
params: args
|
||||
is_variadic: is_variadic
|
||||
return_type: return_type
|
||||
return_type_pos: return_type_pos
|
||||
}
|
||||
// MapFooFn typedefs are manually added in cheaders.v
|
||||
// because typedefs get generated after the map struct is generated
|
||||
|
|
|
@ -3073,6 +3073,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
|||
}
|
||||
is_public: is_pub
|
||||
})
|
||||
type_end_pos := p.prev_tok.position()
|
||||
if idx == -1 {
|
||||
p.error_with_pos('cannot register alias `$name`, another type with this name exists',
|
||||
decl_pos.extend(type_alias_pos))
|
||||
|
@ -3087,7 +3088,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
|||
name: name
|
||||
is_pub: is_pub
|
||||
parent_type: parent_type
|
||||
type_pos: type_pos
|
||||
type_pos: type_pos.extend(type_end_pos)
|
||||
pos: decl_pos
|
||||
comments: comments
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue