@@ -12,6 +12,7 @@ import (
12
12
"go/ast"
13
13
"go/types"
14
14
"slices"
15
+ "strconv"
15
16
16
17
"golang.org/x/tools/go/analysis"
17
18
"golang.org/x/tools/go/analysis/passes/inspect"
@@ -27,6 +28,10 @@ import (
27
28
// with a call to go1.21's slices.Concat(base, a, b, c), or simpler
28
29
// replacements such as slices.Clone(a) in degenerate cases.
29
30
//
31
+ // We offer bytes.Clone in preference to slices.Clone where
32
+ // appropriate, if the package already imports "bytes";
33
+ // their behaviors are identical.
34
+ //
30
35
// The base expression must denote a clipped slice (see [isClipped]
31
36
// for definition), otherwise the replacement might eliminate intended
32
37
// side effects to the base slice's array.
@@ -41,7 +46,8 @@ import (
41
46
// The fix does not always preserve nilness the of base slice when the
42
47
// addends (a, b, c) are all empty.
43
48
func appendclipped (pass * analysis.Pass ) {
44
- if pass .Pkg .Path () == "slices" {
49
+ switch pass .Pkg .Path () {
50
+ case "slices" , "bytes" :
45
51
return
46
52
}
47
53
@@ -94,15 +100,32 @@ func appendclipped(pass *analysis.Pass) {
94
100
}
95
101
}
96
102
97
- // append(zerocap, s...) -> slices.Clone(s)
98
- _ , prefix , importEdits := analysisinternal .AddImport (info , file , "slices" , "slices" , "Clone" , call .Pos ())
103
+ // If the slice type is []byte, and the file imports
104
+ // "bytes" but not "slices", prefer the (behaviorally
105
+ // identical) bytes.Clone for local consistency.
106
+ // https://go.dev/issue/70815#issuecomment-2671572984
107
+ fileImports := func (path string ) bool {
108
+ return slices .ContainsFunc (file .Imports , func (spec * ast.ImportSpec ) bool {
109
+ value , _ := strconv .Unquote (spec .Path .Value )
110
+ return value == path
111
+ })
112
+ }
113
+ clonepkg := cond (
114
+ types .Identical (info .TypeOf (call ), byteSliceType ) &&
115
+ ! fileImports ("slices" ) && fileImports ("bytes" ),
116
+ "bytes" ,
117
+ "slices" )
118
+
119
+ // append(zerocap, s...) -> slices.Clone(s) or bytes.Clone(s)
120
+ _ , prefix , importEdits := analysisinternal .AddImport (info , file , clonepkg , clonepkg , "Clone" , call .Pos ())
121
+ message := fmt .Sprintf ("Replace append with %s.Clone" , clonepkg )
99
122
pass .Report (analysis.Diagnostic {
100
123
Pos : call .Pos (),
101
124
End : call .End (),
102
125
Category : "slicesclone" ,
103
- Message : "Replace append with slices.Clone" ,
126
+ Message : message ,
104
127
SuggestedFixes : []analysis.SuggestedFix {{
105
- Message : "Replace append with slices.Clone" ,
128
+ Message : message ,
106
129
TextEdits : append (importEdits , []analysis.TextEdit {{
107
130
Pos : call .Pos (),
108
131
End : call .End (),
0 commit comments