Skip to content

Commit

Permalink
checker: fix assigning array slice in struct init (#19150)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Aug 16, 2023
1 parent 06e2bc5 commit d0e6057
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
3 changes: 2 additions & 1 deletion vlib/v/checker/assign.v
Expand Up @@ -483,7 +483,8 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
}
}
}
} else if mut left is ast.Ident && right is ast.IndexExpr {
} else if mut left is ast.Ident && left.kind != .blank_ident
&& right is ast.IndexExpr {
if (right as ast.IndexExpr).left is ast.Ident
&& (right as ast.IndexExpr).index is ast.RangeExpr
&& ((right as ast.IndexExpr).left.is_mut() || left.is_mut())
Expand Down
24 changes: 24 additions & 0 deletions vlib/v/checker/struct.v
Expand Up @@ -566,6 +566,30 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
&& !got_type.is_ptr() {
c.error('allocate on the heap for use in other functions', init_field.pos)
}
if exp_type_sym.kind == .array && got_type_sym.kind == .array {
if init_field.expr is ast.IndexExpr
&& (init_field.expr as ast.IndexExpr).left is ast.Ident
&& ((init_field.expr as ast.IndexExpr).left.is_mut()
|| field_info.is_mut) && init_field.expr.index is ast.RangeExpr
&& !c.inside_unsafe {
// `a: arr[..]` auto add clone() -> `a: arr[..].clone()`
c.add_error_detail_with_pos('To silence this notice, use either an explicit `a[..].clone()`,
or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
init_field.expr.pos())
c.note('an implicit clone of the slice was done here', init_field.expr.pos())
mut right := ast.CallExpr{
name: 'clone'
left: init_field.expr
left_type: got_type
is_method: true
receiver_type: got_type.ref()
return_type: got_type
scope: c.fn_scope
}
got_type = c.expr(mut right)
node.init_fields[i].expr = right
}
}
if exp_type_sym.kind == .interface_ {
if c.type_implements(got_type, exp_type, init_field.pos) {
if !c.inside_unsafe && got_type_sym.kind != .interface_
Expand Down
15 changes: 15 additions & 0 deletions vlib/v/checker/tests/slice_clone_in_struct_init_notice.out
@@ -0,0 +1,15 @@
vlib/v/checker/tests/slice_clone_in_struct_init_notice.vv:9:7: notice: an implicit clone of the slice was done here
7 |
8 | _ := AA{
9 | a: a[0..5]
| ~~~~~~
10 | }
11 | _ := a[0..5]
Details: vlib/v/checker/tests/slice_clone_in_struct_init_notice.vv:9:7: details: To silence this notice, use either an explicit `a[..].clone()`,
or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.
7 |
8 | _ := AA{
9 | a: a[0..5]
| ~~~~~~
10 | }
11 | _ := a[0..5]
12 changes: 12 additions & 0 deletions vlib/v/checker/tests/slice_clone_in_struct_init_notice.vv
@@ -0,0 +1,12 @@
struct AA {
a []int
}

fn main() {
mut a := []int{len: 10}

_ := AA{
a: a[0..5]
}
_ := a[0..5]
}

0 comments on commit d0e6057

Please sign in to comment.