mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker, cgen: fix check and cgen for match x { StructName {} }
and match x { y {} }
, where x
is a mutable receiver (#17755)
This commit is contained in:
parent
17c4eb49fb
commit
0a8a0fdb0e
|
@ -194,6 +194,10 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
|
|||
// ensure that the sub expressions of the branch are actually checked, before anything else:
|
||||
_ := c.expr(expr)
|
||||
}
|
||||
if expr is ast.TypeNode && cond_sym.kind == .struct_ {
|
||||
c.error('struct instances cannot be matched by type name, they can only be matched to other instances of the same struct type',
|
||||
branch.pos)
|
||||
}
|
||||
if mut expr is ast.RangeExpr {
|
||||
// Allow for `match enum_value { 4..5 { } }`, even though usually int and enum values,
|
||||
// are considered incompatible outside unsafe{}, and are not allowed to be compared directly
|
||||
|
|
7
vlib/v/checker/tests/struct_match_same_type_node.out
Normal file
7
vlib/v/checker/tests/struct_match_same_type_node.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/struct_match_same_type_node.vv:10:3: error: struct instances cannot be matched by type name, they can only be matched to other instances of the same struct type
|
||||
8 | fn (mut t Type) returns() Union {
|
||||
9 | match t {
|
||||
10 | Type {
|
||||
| ~~~~
|
||||
11 | t.something = 'else'
|
||||
12 | }
|
25
vlib/v/checker/tests/struct_match_same_type_node.vv
Normal file
25
vlib/v/checker/tests/struct_match_same_type_node.vv
Normal file
|
@ -0,0 +1,25 @@
|
|||
struct Type {
|
||||
mut:
|
||||
something string
|
||||
}
|
||||
|
||||
type Union = Type
|
||||
|
||||
fn (mut t Type) returns() Union {
|
||||
match t {
|
||||
Type {
|
||||
t.something = 'else'
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut t := &Type{
|
||||
something: 'something'
|
||||
}
|
||||
t.returns()
|
||||
println(t)
|
||||
}
|
|
@ -472,8 +472,10 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
|||
g.write(')')
|
||||
}
|
||||
.struct_ {
|
||||
derefs_expr := '*'.repeat(g.get_expr_type(expr).nr_muls())
|
||||
derefs_ctype := '*'.repeat(node.cond_type.nr_muls())
|
||||
ptr_typ := g.equality_fn(node.cond_type)
|
||||
g.write('${ptr_typ}_struct_eq(${cond_var}, ')
|
||||
g.write('${ptr_typ}_struct_eq(${derefs_ctype}${cond_var}, ${derefs_expr}')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
|
|
69
vlib/v/tests/match_struct_type_test.v
Normal file
69
vlib/v/tests/match_struct_type_test.v
Normal file
|
@ -0,0 +1,69 @@
|
|||
struct Type {
|
||||
mut:
|
||||
something string
|
||||
}
|
||||
|
||||
fn (mut t Type) match_mut_receiver_against_zero_struct_value() {
|
||||
zero := Type{}
|
||||
match t {
|
||||
zero {
|
||||
t.something = 'else'
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
fn (t &Type) match_ref_receiver_against_zero_struct_value() bool {
|
||||
zero := Type{}
|
||||
match t {
|
||||
zero {
|
||||
return true
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fn test_match_struct_type_mut_receiver() {
|
||||
mut a := &Type{}
|
||||
a.match_mut_receiver_against_zero_struct_value()
|
||||
assert a.something == 'else'
|
||||
mut b := &Type{
|
||||
something: 'another'
|
||||
}
|
||||
b.match_mut_receiver_against_zero_struct_value()
|
||||
assert b.something == 'another'
|
||||
}
|
||||
|
||||
fn test_match_struct_type_mut_receiver_with_non_ref_receiver_in_caller() {
|
||||
mut a := Type{}
|
||||
a.match_mut_receiver_against_zero_struct_value()
|
||||
assert a.something == 'else'
|
||||
mut b := Type{
|
||||
something: 'another'
|
||||
}
|
||||
b.match_mut_receiver_against_zero_struct_value()
|
||||
assert b.something == 'another'
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fn test_match_struct_type_ref_receiver() {
|
||||
a := &Type{}
|
||||
assert a.match_ref_receiver_against_zero_struct_value()
|
||||
b := &Type{
|
||||
something: 'another'
|
||||
}
|
||||
assert !b.match_ref_receiver_against_zero_struct_value()
|
||||
}
|
||||
|
||||
fn test_match_struct_type_ref_receiver_with_non_ref_receiver_in_caller() {
|
||||
a := Type{}
|
||||
assert a.match_ref_receiver_against_zero_struct_value()
|
||||
b := Type{
|
||||
something: 'another'
|
||||
}
|
||||
assert !b.match_ref_receiver_against_zero_struct_value()
|
||||
}
|
Loading…
Reference in New Issue
Block a user