Skip to content

x/tools/go/ssa: single-case select evaluates receive-assignment LHS too early #80863

Description

@cpunion

Go version

go version go1.26.5 darwin/arm64

golang.org/x/tools master at a5c4651b8e4951086fc536519d0eb869feefa7cb.

What did you do?

I built and interpreted this program with cmd/ssadump from the latest
x/tools master:

package main

var (
	c     = make(chan int, 1)
	x     int
	order [2]int
	n     int
)

func fc() chan int {
	order[n] = 1
	n++
	return c
}

func fp() *int {
	order[n] = 100
	n++
	return &x
}

func main() {
	c <- 1
	select {
	case *fp() = <-fc():
	}
	println(order[0], order[1])
}
$ go run .
1 100

$ go run golang.org/x/tools/cmd/ssadump@master -build=C -run .
100 1

The relevant SSA is:

t0 = fp()
t1 = fc()
t2 = <-t1
*t0 = t2

What did you expect to see?

The SSA interpreter should print 1 100, and the SSA should evaluate fc,
perform the receive, and only then evaluate fp.

The select statement rules say that receive-assignment left-hand-side
expressions are not evaluated when entering the select. They are evaluated
only after a communication is selected and the receive is performed:
https://go.dev/ref/spec#Select_statements

What did you see instead?

The single-case optimization in builder.selectStmt lowers the communication
as an ordinary assignment statement. Ordinary assignment lowering evaluates
the LHS before the RHS, so fp runs before fc and the receive. This changes
observable side effects.

The general multi-case select lowering does not have this particular ordering
problem because it evaluates the channel and performs the select before
building the receive-assignment LHS.

Downstream context

LLGo currently repairs the generated SSA after construction. The downstream
workaround and regression tests are in:
xgo-dev/llgo#1805

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.ToolsThis label describes issues relating to any tools in the x/tools repository.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions