go/test/escape_unique.go
Cherry Mui 5e6a868b28 cmd/compile, unique: model data flow of non-string pointers
Currently, hash/maphash.Comparable escapes its parameter if it
contains non-string pointers, but does not escape strings or types
that contain strings but no other pointers. This is achieved by a
compiler intrinsic.

unique.Make does something similar: it stores its parameter to a
central map, with strings cloned. So from the escape analysis's
perspective, the non-string pointers are passed through, whereas
string pointers are not. We currently cannot model this type of
type-dependent data flow directly in Go. So we do this with a
compiler intrinsic. In fact, we can unify this and the intrinsic
above.

Tests are from Jake Bailey's CL 671955 (thanks!).

Fixes #73680.

Change-Id: Ia6a78e09dee39f8d9198a16758e4b5322ee2c56a
Reviewed-on: https://go-review.googlesource.com/c/go/+/675156
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Jake Bailey <jacob.b.bailey@gmail.com>
2025-05-21 20:07:36 -07:00

63 lines
1.4 KiB
Go

// errorcheck -0 -m -l
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test escape analysis for unique.
package escape
import "unique"
type T string
func f1(s string) unique.Handle[string] { // ERROR "s does not escape$"
return unique.Make(s)
}
func f1a(s []byte) unique.Handle[string] { // ERROR "s does not escape$"
return unique.Make(string(s)) // ERROR "string\(s\) does not escape$"
}
func gen[S ~string](s S) unique.Handle[S] {
return unique.Make(s)
}
func f2(s T) unique.Handle[T] { // ERROR "s does not escape$"
return unique.Make(s)
}
func f3(s T) unique.Handle[T] { // ERROR "s does not escape$"
return gen(s)
}
type pair struct {
s1 string
s2 string
}
func f4(s1 string, s2 string) unique.Handle[pair] { // ERROR "s1 does not escape$" "s2 does not escape$"
return unique.Make(pair{s1, s2})
}
type viaInterface struct {
s any
}
func f5(s string) unique.Handle[viaInterface] { // ERROR "leaking param: s$"
return unique.Make(viaInterface{s}) // ERROR "s escapes to heap$"
}
var sink any
func f6(s string) unique.Handle[string] { // ERROR "leaking param: s$"
sink = s // ERROR "s escapes to heap$"
return unique.Make(s)
}
func f6a(s []byte) unique.Handle[string] { // ERROR "leaking param: s$"
sink = s // ERROR "s escapes to heap$"
return unique.Make(string(s)) // ERROR "string\(s\) does not escape$"
}