Skip to content

Commit 5a46e4d

Browse files
xieyuschengopherbot
authored andcommitted
gopls/internal/analysis/modernize/slicesdelete: convert index type if needed
As go compiler has a rule "the index x must be an untyped constant or its core type must be an integer" but slices.Delete accepts the int only, the compatible index type may break type checking after applying modernize fix. This CL checks whether the index type is int type, and converts it to int by 'int(expr)'. Fixes golang/go#73663 Change-Id: I13553e8149baa290f8a0793ed5615481a1418919 Reviewed-on: https://go-review.googlesource.com/c/tools/+/671735 Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent c460ea9 commit 5a46e4d

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

gopls/internal/analysis/modernize/modernize.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ var (
177177
builtinAny = types.Universe.Lookup("any")
178178
builtinAppend = types.Universe.Lookup("append")
179179
builtinBool = types.Universe.Lookup("bool")
180+
builtinInt = types.Universe.Lookup("int")
180181
builtinFalse = types.Universe.Lookup("false")
181182
builtinLen = types.Universe.Lookup("len")
182183
builtinMake = types.Universe.Lookup("make")

gopls/internal/analysis/modernize/slicesdelete.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,39 @@ func slicesdelete(pass *analysis.Pass) {
4545
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
4646
info := pass.TypesInfo
4747
report := func(file *ast.File, call *ast.CallExpr, slice1, slice2 *ast.SliceExpr) {
48+
insert := func(pos token.Pos, text string) analysis.TextEdit {
49+
return analysis.TextEdit{Pos: pos, End: pos, NewText: []byte(text)}
50+
}
51+
isIntExpr := func(e ast.Expr) bool {
52+
return types.Identical(types.Default(info.TypeOf(e)), builtinInt.Type())
53+
}
54+
isIntShadowed := func() bool {
55+
scope := pass.TypesInfo.Scopes[file].Innermost(call.Lparen)
56+
if _, obj := scope.LookupParent("int", call.Lparen); obj != builtinInt {
57+
return true // int type is shadowed
58+
}
59+
return false
60+
}
61+
4862
_, prefix, edits := analysisinternal.AddImport(info, file, "slices", "slices", "Delete", call.Pos())
63+
// append's indices may be any integer type; slices.Delete requires int.
64+
// Insert int conversions as needed (and if possible).
65+
if isIntShadowed() && (!isIntExpr(slice1.High) || !isIntExpr(slice2.Low)) {
66+
return
67+
}
68+
if !isIntExpr(slice1.High) {
69+
edits = append(edits,
70+
insert(slice1.High.Pos(), "int("),
71+
insert(slice1.High.End(), ")"),
72+
)
73+
}
74+
if !isIntExpr(slice2.Low) {
75+
edits = append(edits,
76+
insert(slice2.Low.Pos(), "int("),
77+
insert(slice2.Low.End(), ")"),
78+
)
79+
}
80+
4981
pass.Report(analysis.Diagnostic{
5082
Pos: call.Pos(),
5183
End: call.End(),
@@ -123,7 +155,6 @@ func slicesdelete(pass *analysis.Pass) {
123155
// Given two slice indices a and b, returns true if we can verify that a < b.
124156
// It recognizes certain forms such as i+k1 < i+k2 where k1 < k2.
125157
func increasingSliceIndices(info *types.Info, a, b ast.Expr) bool {
126-
127158
// Given an expression of the form i±k, returns (i, k)
128159
// where k is a signed constant. Otherwise it returns (e, 0).
129160
split := func(e ast.Expr) (ast.Expr, constant.Value) {

gopls/internal/analysis/modernize/testdata/src/slicesdelete/slicesdelete.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,15 @@ func slicesdelete(test, other []byte, i int) {
4242

4343
_ = append(test[:1+2], test[i-1:]...) // cannot verify a < b
4444
}
45+
46+
func issue73663(test, other []byte, i int32) {
47+
const k = 1
48+
_ = append(test[:i], test[i+1:]...) // want "Replace append with slices.Delete"
49+
50+
_ = append(test[:i-1], test[i:]...) // want "Replace append with slices.Delete"
51+
52+
_ = append(g.f[:i], g.f[i+k:]...) // want "Replace append with slices.Delete"
53+
54+
type int string // int is shadowed, so no offered fix.
55+
_ = append(test[:i], test[i+1:]...)
56+
}

gopls/internal/analysis/modernize/testdata/src/slicesdelete/slicesdelete.go.golden

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,15 @@ func slicesdelete(test, other []byte, i int) {
4444

4545
_ = append(test[:1+2], test[i-1:]...) // cannot verify a < b
4646
}
47+
48+
func issue73663(test, other []byte, i int32) {
49+
const k = 1
50+
_ = slices.Delete(test, int(i), int(i+1)) // want "Replace append with slices.Delete"
51+
52+
_ = slices.Delete(test, int(i-1), int(i)) // want "Replace append with slices.Delete"
53+
54+
_ = slices.Delete(g.f, int(i), int(i+k)) // want "Replace append with slices.Delete"
55+
56+
type int string // int is shadowed, so no offered fix.
57+
_ = append(test[:i], test[i+1:]...)
58+
}

0 commit comments

Comments
 (0)