checker: ban any_int/any_float outside buitlin (#7675)

pull/7750/head
Swastik Baranwal 2020-12-31 17:11:30 +05:30 committed by GitHub
parent 3e44393152
commit a9ab79d301
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 88 additions and 21 deletions

View File

@ -292,17 +292,17 @@ pub:
is_variadic bool
is_anon bool
receiver Field
receiver_pos token.Position
receiver_pos token.Position // `(u User)` in `fn (u User) name()` position
is_method bool
method_type_pos token.Position
method_type_pos token.Position // `User` in ` fn (u User)` position
method_idx int
rec_mut bool // is receiver mutable
rec_share table.ShareType
language table.Language
no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv
pos token.Position
body_pos token.Position
pos token.Position // function declaration position
body_pos token.Position // function bodys position
file string
is_generic bool
is_direct_arr bool // direct array access

View File

@ -316,7 +316,7 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
c.check_valid_pascal_case(node.name, 'type alias', node.pos)
}
typ_sym := c.table.get_type_symbol(node.parent_type)
if typ_sym.kind == .placeholder {
if typ_sym.kind in [.placeholder, .any_int, .any_float] {
c.error("type `$typ_sym.name` doesn't exist", node.pos)
} else if typ_sym.kind == .alias {
orig_sym := c.table.get_type_symbol((typ_sym.info as table.Alias).parent_type)
@ -353,10 +353,10 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
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 == .placeholder {
c.error("type `$sym.name` doesn't exist", node.pos)
} else if sym.kind in [.placeholder, .any_int, .any_float] {
c.error("type `$sym.name` doesn't exist", variant.pos)
} else if sym.kind == .interface_ {
c.error('sum type cannot hold an interface', node.pos)
c.error('sum type cannot hold an interface', variant.pos)
}
names_used << sym.name
}
@ -397,6 +397,16 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `$sym.name`'),
field.type_pos)
}
// Separate error condition for `any_int` and `any_float` because `util.suggestion` may give different
// suggestions due to f32 comparision issue.
if sym.kind in [.any_int, .any_float] {
msg := if sym.kind == .any_int {
'unknown type `$sym.name`.\nDid you mean `int`?'
} else {
'unknown type `$sym.name`.\nDid you mean `f64`?'
}
c.error(msg, field.type_pos)
}
if sym.kind == .array {
array_info := sym.array_info()
elem_sym := c.table.get_type_symbol(array_info.elem_type)
@ -4861,11 +4871,17 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
// Make sure all types are valid
for arg in node.params {
sym := c.table.get_type_symbol(arg.typ)
if sym.kind == .placeholder {
c.error('unknown type `$sym.name`', node.method_type_pos)
if sym.kind == .placeholder ||
(sym.kind in [table.Kind.any_int, .any_float] && !c.is_builtin_mod) {
c.error('unknown type `$sym.name`', node.pos)
}
}
}
return_sym := c.table.get_type_symbol(node.return_type)
if node.language == .v &&
return_sym.kind in [.placeholder, .any_int, .any_float] && return_sym.language == .v {
c.error('unknown type `$return_sym.name`', node.pos)
}
if node.language == .v && node.is_method && node.name == 'str' {
if node.return_type != table.string_type {
c.error('.str() methods should return `string`', node.pos)

View File

@ -0,0 +1,41 @@
vlib/v/checker/tests/any_int_float_ban_err.vv:1:12: error: type `any_int` doesn't exist
1 | type Foo = any_int | any_float
| ~~~~~~~
2 | type Fo2 = any_int
3 |
vlib/v/checker/tests/any_int_float_ban_err.vv:2:1: error: type `any_int` doesn't exist
1 | type Foo = any_int | any_float
2 | type Fo2 = any_int
| ~~~~~~~~
3 |
4 | struct Int {
vlib/v/checker/tests/any_int_float_ban_err.vv:5:7: error: unknown type `any_int`.
Did you mean `int`?
3 |
4 | struct Int {
5 | i any_int
| ~~~~~~~
6 | f any_float
7 | }
vlib/v/checker/tests/any_int_float_ban_err.vv:6:7: error: unknown type `any_float`.
Did you mean `f64`?
4 | struct Int {
5 | i any_int
6 | f any_float
| ~~~~~~~~~
7 | }
8 |
vlib/v/checker/tests/any_int_float_ban_err.vv:9:1: error: unknown type `any_int`
7 | }
8 |
9 | fn foo(i any_int) any_int {
| ~~~~~~~~~~~~~~~~~~~~~~~~~
10 | return i
11 | }
vlib/v/checker/tests/any_int_float_ban_err.vv:13:1: error: unknown type `any_int`
11 | }
12 |
13 | fn foo2() any_int {
| ~~~~~~~~~~~~~~~~~
14 | return 1
15 | }

View File

@ -0,0 +1,15 @@
type Foo = any_int | any_float
type Fo2 = any_int
struct Int {
i any_int
f any_float
}
fn foo(i any_int) any_int {
return i
}
fn foo2() any_int {
return 1
}

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/sum_type_exists.vv:1:1: error: type `Nope` doesn't exist
vlib/v/checker/tests/sum_type_exists.vv:1:22: error: type `Nope` doesn't exist
1 | type Miscellaneous = Nope | Inexistant | int
| ~~~~~~~~~~~~~~~~~~
2 |
| ~~~~
2 |
3 | fn main() {

View File

@ -732,7 +732,8 @@ pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
pub fn (table &Table) known_type_names() []string {
mut res := []string{}
for _, idx in table.type_idxs {
if idx == 0 {
// Skip `any_int_type_idx` and `any_flt_type_idx` because they shouldn't be visible to the User.
if idx in [0, any_int_type_idx, any_flt_type_idx] {
continue
}
res << table.type_to_str(idx)

View File

@ -11,7 +11,7 @@ import v.util
import v.pref
// `Any` is a sum type that lists the possible types to be decoded and used.
pub type Any = string | int | i64 | f32 | f64 | any_int | any_float | bool | Null | []Any | map[string]Any
pub type Any = string | int | i64 | f32 | f64 | bool | Null | []Any | map[string]Any
// `Null` struct is a simple representation of the `null` value in JSON.
pub struct Null {

View File

@ -79,12 +79,6 @@ pub fn (f Any) str() string {
str_f64
}
}
any_int {
return f.str()
}
any_float {
return f.str()
}
bool {
return f.str()
}