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:
parent
6016f28171
commit
b2fee21ef3
@ -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 {
|
||||
|
@ -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 | }
|
12
vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv
Normal file
12
vlib/v/checker/tests/struct_cast_to_struct_generic_err.vv
Normal file
@ -0,0 +1,12 @@
|
||||
struct Abc<T> {
|
||||
name T
|
||||
}
|
||||
|
||||
struct Xyz {
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc<int>{}
|
||||
_ := Xyz(abc)
|
||||
}
|
6
vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out
Normal file
6
vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.out
Normal 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 | }
|
13
vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.vv
Normal file
13
vlib/v/checker/tests/struct_cast_to_struct_mut_err_a.vv
Normal file
@ -0,0 +1,13 @@
|
||||
struct Abc {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
struct Xyz {
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc{}
|
||||
_ := Xyz(abc)
|
||||
}
|
6
vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out
Normal file
6
vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.out
Normal 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 | }
|
13
vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.vv
Normal file
13
vlib/v/checker/tests/struct_cast_to_struct_mut_err_b.vv
Normal file
@ -0,0 +1,13 @@
|
||||
struct Abc {
|
||||
name string
|
||||
}
|
||||
|
||||
struct Xyz {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc{}
|
||||
_ := Xyz(abc)
|
||||
}
|
6
vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out
Normal file
6
vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.out
Normal 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 | }
|
13
vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.vv
Normal file
13
vlib/v/checker/tests/struct_cast_to_struct_pub_err_a.vv
Normal file
@ -0,0 +1,13 @@
|
||||
struct Abc {
|
||||
pub:
|
||||
name string
|
||||
}
|
||||
|
||||
struct Xyz {
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc{}
|
||||
_ := Xyz(abc)
|
||||
}
|
6
vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out
Normal file
6
vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.out
Normal 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 | }
|
13
vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.vv
Normal file
13
vlib/v/checker/tests/struct_cast_to_struct_pub_err_b.vv
Normal file
@ -0,0 +1,13 @@
|
||||
struct Abc {
|
||||
name string
|
||||
}
|
||||
|
||||
struct Xyz {
|
||||
pub:
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc := Abc{}
|
||||
_ := Xyz(abc)
|
||||
}
|
@ -5,7 +5,7 @@ struct Foo {
|
||||
|
||||
struct Bar {
|
||||
f &Foo = &Foo(0)
|
||||
d Foo = Foo(0)
|
||||
d Foo = Foo{0}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user