diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index c97020cc58..fe42fe7533 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -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()) diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 320e306f3a..6b5c3fa6c5 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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_ diff --git a/vlib/v/checker/tests/slice_clone_in_struct_init_notice.out b/vlib/v/checker/tests/slice_clone_in_struct_init_notice.out new file mode 100644 index 0000000000..153f737404 --- /dev/null +++ b/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] diff --git a/vlib/v/checker/tests/slice_clone_in_struct_init_notice.vv b/vlib/v/checker/tests/slice_clone_in_struct_init_notice.vv new file mode 100644 index 0000000000..51f63d88b5 --- /dev/null +++ b/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] +}