1
0
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:
Swastik Baranwal 2023-03-25 18:08:47 +05:30 committed by GitHub
parent 17c4eb49fb
commit 0a8a0fdb0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 1 deletions

View File

@ -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

View 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 | }

View 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)
}

View File

@ -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(')')
}

View 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()
}