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:
|
// ensure that the sub expressions of the branch are actually checked, before anything else:
|
||||||
_ := c.expr(expr)
|
_ := 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 {
|
if mut expr is ast.RangeExpr {
|
||||||
// Allow for `match enum_value { 4..5 { } }`, even though usually int and enum values,
|
// 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
|
// 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(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
.struct_ {
|
.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)
|
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.expr(expr)
|
||||||
g.write(')')
|
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…
x
Reference in New Issue
Block a user