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

checker: check struct casting (#5864)

This commit is contained in:
Daniel Däschle 2020-08-14 14:57:08 +02:00 committed by GitHub
parent 6016f28171
commit b2fee21ef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 130 additions and 1 deletions

View File

@ -2328,6 +2328,13 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
to_type_sym.kind == .byte {
type_name := c.table.type_to_str(node.expr_type)
c.error('cannot cast type `$type_name` to `byte`', node.pos)
} else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef {
from_type_info := from_type_sym.info as table.Struct
to_type_info := to_type_sym.info as table.Struct
if !c.check_struct_signature(from_type_info, to_type_info) {
c.error('cannot convert struct `$from_type_sym.name` to struct `$to_type_sym.name`',
node.pos)
}
}
if node.has_arg {
c.expr(node.arg)
@ -3257,6 +3264,34 @@ pub fn (mut c Checker) error(message string, pos token.Position) {
c.warn_or_error(msg, pos, false)
}
// check_struct_signature checks if both structs has the same signature / fields for casting
fn (c Checker) check_struct_signature(from, to table.Struct) bool {
if from.fields.len != to.fields.len {
return false
}
for _, field in from.fields {
filtered := to.fields.filter(it.name == field.name)
if filtered.len != 1 {
// field doesn't exist
return false
}
counterpart := filtered[0]
if field.typ != counterpart.typ {
// field has different tye
return false
}
if field.is_pub != counterpart.is_pub {
// field is not public while the other one is
return false
}
if field.is_mut != counterpart.is_mut {
// field is not mutable while the other one is
return false
}
}
return true
}
fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool) {
// add backtrace to issue struct, how?
// if c.pref.is_verbose {

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/struct_cast_to_struct_generic_err.v:11:11: error: cannot convert struct `Abc<int>` to struct `Xyz`
9 | fn main() {
10 | abc := Abc<int>{}
11 | _ := Xyz(abc)
| ~~~
12 | }

View File

@ -0,0 +1,12 @@
struct Abc<T> {
name T
}
struct Xyz {
name string
}
fn main() {
abc := Abc<int>{}
_ := Xyz(abc)
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.v:12:11: error: cannot convert struct `Abc` to struct `Xyz`
10 | fn main() {
11 | abc := Abc{}
12 | _ := Xyz(abc)
| ~~~
13 | }

View File

@ -0,0 +1,13 @@
struct Abc {
mut:
name string
}
struct Xyz {
name string
}
fn main() {
abc := Abc{}
_ := Xyz(abc)
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.v:12:11: error: cannot convert struct `Abc` to struct `Xyz`
10 | fn main() {
11 | abc := Abc{}
12 | _ := Xyz(abc)
| ~~~
13 | }

View File

@ -0,0 +1,13 @@
struct Abc {
name string
}
struct Xyz {
mut:
name string
}
fn main() {
abc := Abc{}
_ := Xyz(abc)
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.v:12:11: error: cannot convert struct `Abc` to struct `Xyz`
10 | fn main() {
11 | abc := Abc{}
12 | _ := Xyz(abc)
| ~~~
13 | }

View File

@ -0,0 +1,13 @@
struct Abc {
pub:
name string
}
struct Xyz {
name string
}
fn main() {
abc := Abc{}
_ := Xyz(abc)
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.v:12:11: error: cannot convert struct `Abc` to struct `Xyz`
10 | fn main() {
11 | abc := Abc{}
12 | _ := Xyz(abc)
| ~~~
13 | }

View File

@ -0,0 +1,13 @@
struct Abc {
name string
}
struct Xyz {
pub:
name string
}
fn main() {
abc := Abc{}
_ := Xyz(abc)
}

View File

@ -5,7 +5,7 @@ struct Foo {
struct Bar {
f &Foo = &Foo(0)
d Foo = Foo(0)
d Foo = Foo{0}
}
fn main() {