# Test closure naming with inlining.

go build -gcflags=-S -o x.exe x.go
# original closure name should appear
stderr 'adder\.func1'
# inlining should not cause the closure to have longer names
! stderr 'F1\.adder\.func1'
! stderr 'F2\.adder\.func1'
# the counter should match the original one, regardless of
# how many closures are in the inlined caller
! stderr 'adder\.func2'
! stderr 'adder\.func3'
! stderr 'adder\.func4'
# user closure counter and range func counter should not
# interfere
stderr 'ranger\.func1'
stderr 'ranger-range1'
stderr 'ranger\.func2'

go tool nm x.exe
# same applies to the nm output
stdout 'adder\.func1'
! stdout 'F1\.adder\.func1'
! stdout 'F2\.adder\.func1'
! stdout 'adder\.func2'
! stdout 'adder\.func3'
! stdout 'adder\.func4'
stdout 'ranger\.func1'
stdout 'ranger-range1'
stdout 'ranger\.func2'
# the inline hash should not make into the final binary
! stdout 'adder\.func1#'

-- x.go --
package main

// keep prevents closures being optimized out
//
//go:noinline
func keep(x func()) func() { return x }

func adder(n int) func(int) int {
	return func(x int) int { return x + n }
}

//go:noinline
func F1() func(int) int {
	// adder is inlined into F1, along with its closure.
	// The closure should still be named addr.func1.
	return adder(1)
}

//go:noinline
func F2() func(int) int {
	keep(func() {})
	keep(func() {})
	keep(func() {})
	// Closures in the outer function should not change
	// the counter. It should still be addr.func1.
	return adder(2)
}

//go:noinline
func iter(yield func(int) bool) {
	_ = yield(1) && yield(2) && yield(3)
}

func ranger() func(int) int {
	keep(func() {}) // func1
	s := 0
	for x := range iter { // range1
		s += x
	}
	return func(x int) int { return s + x } // func2
}

func main() {
	x := 1
	F1()(F2()(ranger()(x)))
}
