Skip to content

x/tools/go/analysis/passes/modernize: minmax changes semantics when arguments have side effects #77558

@findleyr

Description

@findleyr

The minmax modernizer rewrites if/else patterns into calls to min/max, but this changes evaluation semantics when the arguments have side effects. In the if/else form, only one branch executes; with max(a, b), both arguments are always evaluated.

Before (go fix):

package main

import "fmt"

func main() {
	n := 0
	f := func() int { n++; return n }
	x := f()
	if x < f() {
		x = f()
	}
	fmt.Println(x)
}

Output: 3 (f called 3 times: once for initial x=1, once for comparison yielding 2, once in the branch yielding x=3)

After (GOTOOLCHAIN=go1.26.0 go fix):

package main

import "fmt"

func main() {
	n := 0
	f := func() int { n++; return n }
	x := max(f(), f())
	fmt.Println(x)
}

Output: 2 (f called only twice: max(1, 2) = 2)

The original code calls f() three times (initial assignment, comparison, and branch), while the modernized code calls f() only twice. The modernizer should not apply the transformation when the expressions being compared have side effects.

CC @adonovan

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions