Skip to content

Commit fc2161a

Browse files
adonovangopherbot
authored andcommitted
internal/analysis/modernize: minmax: don't reduce to y:=min(x, y)
Fixes golang/go#71111 Change-Id: Ie396f1a6c6b357fbe4c53e2f4e480990397f4d07 Reviewed-on: https://go-review.googlesource.com/c/tools/+/640038 Auto-Submit: Alan Donovan <[email protected]> Commit-Queue: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 155dc6e commit fc2161a

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

gopls/internal/analysis/modernize/minmax.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,23 @@ func minmax(pass *analysis.Pass) {
9898
} else if prev, ok := curIfStmt.PrevSibling(); ok && is[*ast.AssignStmt](prev.Node()) {
9999
fassign := prev.Node().(*ast.AssignStmt)
100100

101-
// Have: lhs2 = rhs2; if a < b { lhs = rhs }
101+
// Have: lhs0 = rhs0; if a < b { lhs = rhs }
102+
//
102103
// For pattern 2, check that
103-
// - lhs = lhs2
104-
// - {rhs,rhs2} = {a,b}, but allow lhs2 to
105-
// stand for rhs2.
106-
// TODO(adonovan): accept "var lhs2 = rhs2" form too.
107-
lhs2 := fassign.Lhs[0]
108-
rhs2 := fassign.Rhs[0]
109-
110-
if equalSyntax(lhs, lhs2) {
111-
if equalSyntax(rhs, a) && (equalSyntax(rhs2, b) || equalSyntax(lhs2, b)) {
104+
// - lhs = lhs0
105+
// - {a,b} = {rhs,rhs0} or {rhs,lhs0}
106+
// The replacement must use rhs0 not lhs0 though.
107+
// For example, we accept this variant:
108+
// lhs = x; if lhs < y { lhs = y } => lhs = min(x, y), not min(lhs, y)
109+
//
110+
// TODO(adonovan): accept "var lhs0 = rhs0" form too.
111+
lhs0 := fassign.Lhs[0]
112+
rhs0 := fassign.Rhs[0]
113+
114+
if equalSyntax(lhs, lhs0) {
115+
if equalSyntax(rhs, a) && (equalSyntax(rhs0, b) || equalSyntax(lhs0, b)) {
112116
sign = +sign
113-
} else if (equalSyntax(rhs2, a) || equalSyntax(lhs2, a)) && equalSyntax(rhs, b) {
117+
} else if (equalSyntax(rhs0, a) || equalSyntax(lhs0, a)) && equalSyntax(rhs, b) {
114118
sign = -sign
115119
} else {
116120
return
@@ -121,6 +125,15 @@ func minmax(pass *analysis.Pass) {
121125
return // min/max function is shadowed
122126
}
123127

128+
// Permit lhs0 to stand for rhs0 in the matching,
129+
// but don't actually reduce to lhs0 = min(lhs0, rhs)
130+
// since the "=" could be a ":=". Use min(rhs0, rhs).
131+
if equalSyntax(lhs0, a) {
132+
a = rhs0
133+
} else if equalSyntax(lhs0, b) {
134+
b = rhs0
135+
}
136+
124137
// pattern 2
125138
pass.Report(analysis.Diagnostic{
126139
// Highlight the condition a < b.
@@ -131,8 +144,8 @@ func minmax(pass *analysis.Pass) {
131144
SuggestedFixes: []analysis.SuggestedFix{{
132145
Message: fmt.Sprintf("Replace if/else with %s", sym),
133146
TextEdits: []analysis.TextEdit{{
134-
// Replace rhs2 and IfStmt with min(a, b)
135-
Pos: rhs2.Pos(),
147+
// Replace rhs0 and IfStmt with min(a, b)
148+
Pos: rhs0.Pos(),
136149
End: ifStmt.End(),
137150
NewText: fmt.Appendf(nil, "%s(%s, %s)",
138151
sym,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,13 @@ func nopeIfStmtHasInitStmt() {
7171
}
7272
print(x)
7373
}
74+
75+
// Regression test for a bug: fix was "y := max(x, y)".
76+
func oops() {
77+
x := 1
78+
y := 2
79+
if x > y { // want "if statement can be modernized using max"
80+
y = x
81+
}
82+
print(y)
83+
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ func ifmax(a, b int) {
1111
}
1212

1313
func ifminvariant(a, b int) {
14-
x := min(x, b)
14+
x := min(a, b)
1515
print(x)
1616
}
1717

1818
func ifmaxvariant(a, b int) {
19-
x := min(a, x)
19+
x := min(a, b)
2020
print(x)
2121
}
2222

@@ -51,3 +51,10 @@ func nopeIfStmtHasInitStmt() {
5151
}
5252
print(x)
5353
}
54+
55+
// Regression test for a bug: fix was "y := max(x, y)".
56+
func oops() {
57+
x := 1
58+
y := max(x, 2)
59+
print(y)
60+
}

0 commit comments

Comments
 (0)