mirror of
https://github.com/golang/go.git
synced 2025-10-22 12:33:19 +00:00

Fixes #75863 Change-Id: I1e5a0f3880dcd5f820a5b6f4540c49b16a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/711141 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Lasse Folger <lassefolger@google.com> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1283 lines
34 KiB
Go
1283 lines
34 KiB
Go
// errorcheck -0 -m
|
|
|
|
// 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.
|
|
|
|
package escape
|
|
|
|
type M interface{ M() }
|
|
|
|
type A interface{ A() }
|
|
|
|
type C interface{ C() }
|
|
|
|
type Impl struct{}
|
|
|
|
func (*Impl) M() {} // ERROR "can inline \(\*Impl\).M$"
|
|
|
|
func (*Impl) A() {} // ERROR "can inline \(\*Impl\).A$"
|
|
|
|
type Impl2 struct{}
|
|
|
|
func (*Impl2) M() {} // ERROR "can inline \(\*Impl2\).M$"
|
|
|
|
func (*Impl2) A() {} // ERROR "can inline \(\*Impl2\).A$"
|
|
|
|
type CImpl struct{}
|
|
|
|
func (CImpl) C() {} // ERROR "can inline CImpl.C$"
|
|
|
|
func typeAsserts() {
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
|
|
a.(M).M() // ERROR "devirtualizing a.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
a.(A).A() // ERROR "devirtualizing a.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a.(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
a.(*Impl).A() // ERROR "inlining call to \(\*Impl\).A"
|
|
|
|
v := a.(M)
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
v.(A).A() // ERROR "devirtualizing v.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v.(*Impl).A() // ERROR "inlining call to \(\*Impl\).A"
|
|
v.(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
|
|
v2 := a.(A)
|
|
v2.A() // ERROR "devirtualizing v2.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v2.(M).M() // ERROR "devirtualizing v2.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
v2.(*Impl).A() // ERROR "inlining call to \(\*Impl\).A"
|
|
v2.(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
|
|
a.(M).(A).A() // ERROR "devirtualizing a.\(M\).\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a.(A).(M).M() // ERROR "devirtualizing a.\(A\).\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
|
|
a.(M).(A).(*Impl).A() // ERROR "inlining call to \(\*Impl\).A"
|
|
a.(A).(M).(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
|
|
any(a).(M).M() // ERROR "devirtualizing any\(a\).\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
any(a).(A).A() // ERROR "devirtualizing any\(a\).\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
any(a).(M).(any).(A).A() // ERROR "devirtualizing any\(a\).\(M\).\(any\).\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
|
|
c := any(a)
|
|
c.(A).A() // ERROR "devirtualizing c.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
c.(M).M() // ERROR "devirtualizing c.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
|
|
M(a).M() // ERROR "devirtualizing M\(a\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
M(M(a)).M() // ERROR "devirtualizing M\(M\(a\)\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
|
|
a2 := a.(A)
|
|
A(a2).A() // ERROR "devirtualizing A\(a2\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
A(A(a2)).A() // ERROR "devirtualizing A\(A\(a2\)\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
|
|
{
|
|
var a C = &CImpl{} // ERROR "&CImpl{} does not escape$"
|
|
a.(any).(C).C() // ERROR "devirtualizing a.\(any\).\(C\).C to \*CImpl$" "inlining call to CImpl.C"
|
|
a.(any).(*CImpl).C() // ERROR "inlining call to CImpl.C"
|
|
}
|
|
}
|
|
|
|
func typeAssertsWithOkReturn() {
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
if v, ok := a.(M); ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
if v, ok := a.(A); ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, ok := a.(M)
|
|
if ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, ok := a.(A)
|
|
if ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, ok := a.(*Impl)
|
|
if ok {
|
|
v.A() // ERROR "inlining call to \(\*Impl\).A"
|
|
v.M() // ERROR "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, _ := a.(M)
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, _ := a.(A)
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v, _ := a.(*Impl)
|
|
v.A() // ERROR "inlining call to \(\*Impl\).A"
|
|
v.M() // ERROR "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
a := newM() // ERROR "&Impl{} does not escape$" "inlining call to newM"
|
|
callA(a) // ERROR "devirtualizing m.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A" "inlining call to callA"
|
|
callIfA(a) // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A" "inlining call to callIfA"
|
|
}
|
|
{
|
|
_, a := newM2ret() // ERROR "&Impl{} does not escape$" "inlining call to newM2ret"
|
|
callA(a) // ERROR "devirtualizing m.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A" "inlining call to callA"
|
|
callIfA(a) // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A" "inlining call to callIfA"
|
|
}
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
// Note the !ok condition, devirtualizing here is fine.
|
|
if v, ok := a.(M); !ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var a A = newImplNoInline()
|
|
if v, ok := a.(M); ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var impl2InA A = &Impl2{} // ERROR "&Impl2{} does not escape$"
|
|
var a A
|
|
a, _ = impl2InA.(*Impl)
|
|
// a now contains the zero value of *Impl
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
a := newANoInline()
|
|
a.A()
|
|
}
|
|
{
|
|
_, a := newANoInlineRet2()
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
func newM() M { // ERROR "can inline newM$"
|
|
return &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
func newM2ret() (int, M) { // ERROR "can inline newM2ret$"
|
|
return -1, &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
func callA(m M) { // ERROR "can inline callA$" "leaking param: m$"
|
|
m.(A).A()
|
|
}
|
|
|
|
func callIfA(m M) { // ERROR "can inline callIfA$" "leaking param: m$"
|
|
if v, ok := m.(A); ok {
|
|
v.A()
|
|
}
|
|
}
|
|
|
|
//go:noinline
|
|
func newImplNoInline() *Impl {
|
|
return &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
//go:noinline
|
|
func newImpl2ret2() (string, *Impl2) {
|
|
return "str", &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
|
|
//go:noinline
|
|
func newImpl2() *Impl2 {
|
|
return &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
|
|
//go:noinline
|
|
func newANoInline() A {
|
|
return &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
//go:noinline
|
|
func newANoInlineRet2() (string, A) {
|
|
return "", &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
func testTypeSwitch() {
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
switch v := v.(type) {
|
|
case A:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
case M:
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
switch v := v.(type) {
|
|
case A:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
case M:
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
v.(M).M() // ERROR "devirtualizing v.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
switch v1 := v.(type) {
|
|
case A:
|
|
v1.A()
|
|
case M:
|
|
v1.M()
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
switch v := v.(type) {
|
|
case A:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
case M:
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
case C:
|
|
v.C()
|
|
}
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
switch v := v.(type) {
|
|
case M:
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
default:
|
|
panic("does not implement M") // ERROR ".does not implement M. escapes to heap$"
|
|
}
|
|
}
|
|
}
|
|
|
|
func differentTypeAssign() {
|
|
{
|
|
var a A
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
{
|
|
a := A(&Impl{}) // ERROR "&Impl{} escapes to heap$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
{
|
|
a := A(&Impl{}) // ERROR "&Impl{} escapes to heap$"
|
|
a.A()
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
{
|
|
a := A(&Impl{}) // ERROR "&Impl{} escapes to heap$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
var asAny any = a
|
|
asAny.(A).A()
|
|
}
|
|
{
|
|
a := A(&Impl{}) // ERROR "&Impl{} escapes to heap$"
|
|
var asAny any = a
|
|
asAny = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
asAny.(A).A()
|
|
}
|
|
{
|
|
a := A(&Impl{}) // ERROR "&Impl{} escapes to heap$"
|
|
var asAny any = a
|
|
asAny.(A).A()
|
|
asAny = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a = newImpl2()
|
|
a.A()
|
|
}
|
|
{
|
|
var a A
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
_, a = newImpl2ret2()
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
func assignWithTypeAssert() {
|
|
{
|
|
var i1 A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
var i2 A = &Impl2{} // ERROR "&Impl2{} does not escape$"
|
|
i1 = i2.(*Impl) // this will panic
|
|
i1.A() // ERROR "devirtualizing i1.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
i2.A() // ERROR "devirtualizing i2.A to \*Impl2$" "inlining call to \(\*Impl2\).A"
|
|
}
|
|
{
|
|
var i1 A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
var i2 A = &Impl2{} // ERROR "&Impl2{} does not escape$"
|
|
i1, _ = i2.(*Impl) // i1 is going to be nil
|
|
i1.A() // ERROR "devirtualizing i1.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
i2.A() // ERROR "devirtualizing i2.A to \*Impl2$" "inlining call to \(\*Impl2\).A"
|
|
}
|
|
}
|
|
|
|
func nilIface() {
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v = nil
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v = nil
|
|
}
|
|
{
|
|
var nilIface A
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v = nilIface
|
|
}
|
|
{
|
|
var nilIface A
|
|
var v A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v = nilIface
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
}
|
|
{
|
|
var v A
|
|
var v2 A = v
|
|
v2.A() // ERROR "devirtualizing v2.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v2 = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
}
|
|
{
|
|
var v A
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
var v2 A = v
|
|
v2.A()
|
|
}
|
|
{
|
|
var v A
|
|
var v2 A
|
|
v2 = v
|
|
v2.A()
|
|
}
|
|
}
|
|
|
|
func longDevirtTest() {
|
|
var a interface {
|
|
M
|
|
A
|
|
} = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
|
|
{
|
|
var b A = a
|
|
b.A() // ERROR "devirtualizing b.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
b.(M).M() // ERROR "devirtualizing b.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var b M = a
|
|
b.M() // ERROR "devirtualizing b.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
b.(A).A() // ERROR "devirtualizing b.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var b A = a.(M).(A)
|
|
b.A() // ERROR "devirtualizing b.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
b.(M).M() // ERROR "devirtualizing b.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var b M = a.(A).(M)
|
|
b.M() // ERROR "devirtualizing b.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
b.(A).A() // ERROR "devirtualizing b.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
if v, ok := a.(A); ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
if v, ok := a.(M); ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
|
|
{
|
|
var c A = a
|
|
|
|
if v, ok := c.(A); ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
c = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
|
|
if v, ok := c.(M); ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
|
|
if v, ok := c.(interface {
|
|
A
|
|
M
|
|
}); ok {
|
|
v.M() // ERROR "devirtualizing v.M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
}
|
|
|
|
func deferDevirt() {
|
|
var a A
|
|
defer func() { // ERROR "can inline deferDevirt.func1$" "func literal does not escape$"
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}()
|
|
a = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
func deferNoDevirt() {
|
|
var a A
|
|
defer func() { // ERROR "can inline deferNoDevirt.func1$" "func literal does not escape$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}()
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
|
|
//go:noinline
|
|
func closureDevirt() {
|
|
var a A
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer so that it does not lnline.
|
|
defer func() {}() // ERROR "can inline closureDevirt.func1.1$" "func literal does not escape$"
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}()
|
|
a = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
//go:noinline
|
|
func closureNoDevirt() {
|
|
var a A
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer so that it does not lnline.
|
|
defer func() {}() // ERROR "can inline closureNoDevirt.func1.1$" "func literal does not escape$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}()
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
|
|
var global = "1"
|
|
|
|
func closureDevirt2() {
|
|
var a A
|
|
a = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
c := func() { // ERROR "can inline closureDevirt2.func1$" "func literal does not escape$"
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
if global == "1" {
|
|
c = func() { // ERROR "can inline closureDevirt2.func2$" "func literal does not escape$"
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
}
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
c()
|
|
}
|
|
|
|
func closureNoDevirt2() {
|
|
var a A
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
c := func() { // ERROR "can inline closureNoDevirt2.func1$" "func literal does not escape$"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
if global == "1" {
|
|
c = func() { // ERROR "can inline closureNoDevirt2.func2$" "func literal does not escape$"
|
|
a = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
}
|
|
a.A()
|
|
c()
|
|
}
|
|
|
|
//go:noinline
|
|
func closureDevirt3() {
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer so that it does not lnline.
|
|
defer func() {}() // ERROR "can inline closureDevirt3.func1.1$" "func literal does not escape$"
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}()
|
|
func() { // ERROR "can inline closureDevirt3.func2$"
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}() // ERROR "inlining call to closureDevirt3.func2" "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
|
|
//go:noinline
|
|
func closureNoDevirt3() {
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer so that it does not lnline.
|
|
defer func() {}() // ERROR "can inline closureNoDevirt3.func1.1$" "func literal does not escape$"
|
|
a.A()
|
|
}()
|
|
func() { // ERROR "can inline closureNoDevirt3.func2$"
|
|
a.A()
|
|
}() // ERROR "inlining call to closureNoDevirt3.func2"
|
|
a = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
|
|
//go:noinline
|
|
func varDeclaredInClosureReferencesOuter() {
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer for noinline
|
|
defer func() {}() // ERROR "can inline varDeclaredInClosureReferencesOuter.func1.1$" "func literal does not escape$"
|
|
var v A = a
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}()
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer for noinline
|
|
defer func() {}() // ERROR "can inline varDeclaredInClosureReferencesOuter.func2.1$" "func literal does not escape$"
|
|
var v A = a
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}()
|
|
|
|
var b A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer for noinline
|
|
defer func() {}() // ERROR "can inline varDeclaredInClosureReferencesOuter.func3.1$" "func literal does not escape$"
|
|
var v A = b
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}()
|
|
func() { // ERROR "func literal does not escape$"
|
|
// defer for noinline
|
|
defer func() {}() // ERROR "can inline varDeclaredInClosureReferencesOuter.func4.1$" "func literal does not escape$"
|
|
var v A = b
|
|
v.A()
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}()
|
|
}
|
|
|
|
//go:noinline
|
|
func testNamedReturn0() (v A) {
|
|
v = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v.A()
|
|
return
|
|
}
|
|
|
|
//go:noinline
|
|
func testNamedReturn1() (v A) {
|
|
v = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v.A()
|
|
return &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
}
|
|
|
|
func testNamedReturns3() (v A) {
|
|
v = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
defer func() { // ERROR "can inline testNamedReturns3.func1$" "func literal does not escape$"
|
|
v.A()
|
|
}()
|
|
v.A()
|
|
return &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
}
|
|
|
|
var (
|
|
globalImpl = &Impl{}
|
|
globalImpl2 = &Impl2{}
|
|
globalA A = &Impl{}
|
|
globalM M = &Impl{}
|
|
)
|
|
|
|
func globals() {
|
|
{
|
|
globalA.A()
|
|
globalA.(M).M()
|
|
globalM.M()
|
|
globalM.(A).A()
|
|
|
|
a := globalA
|
|
a.A()
|
|
a.(M).M()
|
|
|
|
m := globalM
|
|
m.M()
|
|
m.(A).A()
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = globalImpl
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = A(globalImpl)
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = M(globalImpl).(A)
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = globalA.(*Impl)
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a = globalM.(*Impl)
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a = globalImpl2
|
|
a.A()
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a = globalA
|
|
a.A()
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a = globalM.(A)
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
func mapsDevirt() {
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A = m[0]
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
v.(M).M() // ERROR "devirtualizing v.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A
|
|
var ok bool
|
|
if v, ok = m[0]; ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A
|
|
v, _ = m[0]
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
|
|
func mapsNoDevirt() {
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A = m[0]
|
|
v.A()
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.(M).M()
|
|
}
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A
|
|
var ok bool
|
|
if v, ok = m[0]; ok {
|
|
v.A()
|
|
}
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v, _ = m[0]
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
|
|
{
|
|
m := make(map[int]A) // ERROR "make\(map\[int\]A\) does not escape$"
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v = m[0]
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(map[int]A) // ERROR "make\(map\[int\]A\) does not escape$"
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var ok bool
|
|
if v, ok = m[0]; ok {
|
|
v.A()
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(map[int]A) // ERROR "make\(map\[int\]A\) does not escape$"
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v, _ = m[0]
|
|
v.A()
|
|
}
|
|
}
|
|
|
|
func chanDevirt() {
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A = <-m
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
v = <-m
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
v, _ = <-m
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
var ok bool
|
|
if v, ok = <-m; ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
var ok bool
|
|
if v, ok = <-m; ok {
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
select {
|
|
case <-m:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
case v = <-m:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
case v, ok = <-m:
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
}
|
|
|
|
func chanNoDevirt() {
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A = <-m
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
v = <-m
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
v, _ = <-m
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A
|
|
var ok bool
|
|
if v, ok = <-m; ok {
|
|
v.A()
|
|
}
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
var ok bool
|
|
if v, ok = <-m; ok {
|
|
v.A()
|
|
}
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
select {
|
|
case v = <-m:
|
|
v.A()
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
select {
|
|
case v, _ = <-m:
|
|
v.A()
|
|
}
|
|
v.A()
|
|
}
|
|
|
|
{
|
|
m := make(chan A)
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v = <-m
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan A)
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
v, _ = <-m
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan A)
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var ok bool
|
|
if v, ok = <-m; ok {
|
|
v.A()
|
|
}
|
|
}
|
|
{
|
|
m := make(chan A)
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
select {
|
|
case v = <-m:
|
|
v.A()
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
m := make(chan A)
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
select {
|
|
case v, _ = <-m:
|
|
v.A()
|
|
}
|
|
v.A()
|
|
}
|
|
}
|
|
|
|
func rangeDevirt() {
|
|
{
|
|
var v A
|
|
m := make(map[*Impl]struct{}) // ERROR "make\(map\[\*Impl\]struct {}\) does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := make(map[*Impl]*Impl) // ERROR "make\(map\[\*Impl\]\*Impl\) does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := make(map[*Impl]*Impl) // ERROR "make\(map\[\*Impl\]\*Impl\) does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := make(chan *Impl)
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := []*Impl{} // ERROR "\[\]\*Impl{} does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
impl := &Impl{} // ERROR "&Impl{} does not escape$"
|
|
i := 0
|
|
for v = impl; i < 10; i++ {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
impl := &Impl{} // ERROR "&Impl{} does not escape$"
|
|
i := 0
|
|
for v = impl; i < 10; i++ {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := [1]*Impl{&Impl{}} // ERROR "&Impl{} does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var v A
|
|
m := [1]*Impl{&Impl{}} // ERROR "&Impl{} does not escape$"
|
|
v = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
for _, v = range &m {
|
|
}
|
|
v.A() // ERROR "devirtualizing v.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
|
|
func rangeNoDevirt() {
|
|
{
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
m := make(map[*Impl]struct{}) // ERROR "make\(map\[\*Impl\]struct {}\) does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
m := make(map[*Impl]*Impl) // ERROR "make\(map\[\*Impl\]\*Impl\) does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
m := make(map[*Impl]*Impl) // ERROR "make\(map\[\*Impl\]\*Impl\) does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
m := make(chan *Impl)
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
m := []*Impl{} // ERROR "\[\]\*Impl{} does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
impl := &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
i := 0
|
|
for v = impl; i < 10; i++ {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
impl := &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
i := 0
|
|
for v = impl; i < 10; i++ {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
m := [1]*Impl{&Impl{}} // ERROR "&Impl{} escapes to heap$"
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
m := [1]*Impl{&Impl{}} // ERROR "&Impl{} escapes to heap$"
|
|
v = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
for _, v = range &m {
|
|
}
|
|
v.A()
|
|
}
|
|
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
m := make(map[A]struct{}) // ERROR "make\(map\[A\]struct {}\) does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
m := make(map[A]A) // ERROR "make\(map\[A\]A\) does not escape$"
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
m := make(map[A]A) // ERROR "make\(map\[A\]A\) does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
m := make(chan A)
|
|
for v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
m := []A{} // ERROR "\[\]A{} does not escape$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
|
|
{
|
|
var v A
|
|
m := [1]A{&Impl{}} // ERROR "&Impl{} escapes to heap$"
|
|
v = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
for _, v = range m {
|
|
}
|
|
v.A()
|
|
}
|
|
{
|
|
var v A
|
|
m := [1]A{&Impl{}} // ERROR "&Impl{} escapes to heap$"
|
|
v = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
for _, v = range &m {
|
|
}
|
|
v.A()
|
|
}
|
|
}
|
|
|
|
var globalInt = 1
|
|
|
|
func testIfInit() {
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
var i = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
if a = i; globalInt == 1 {
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a.(M).M() // ERROR "devirtualizing a.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var i2 = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
if a = i2; globalInt == 1 {
|
|
a.A()
|
|
}
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
func testSwitchInit() {
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
var i = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
switch a = i; globalInt {
|
|
case 12:
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a.(M).M() // ERROR "devirtualizing a.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var i2 = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
switch a = i2; globalInt {
|
|
case 12:
|
|
a.A()
|
|
}
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
type implWrapper Impl
|
|
|
|
func (implWrapper) A() {} // ERROR "can inline implWrapper.A$"
|
|
|
|
//go:noinline
|
|
func devirtWrapperType() {
|
|
{
|
|
i := &Impl{} // ERROR "&Impl{} does not escape$"
|
|
// This is an OCONVNOP, so we have to be careful, not to devirtualize it to Impl.A.
|
|
var a A = (*implWrapper)(i)
|
|
a.A() // ERROR "devirtualizing a.A to \*implWrapper$" "inlining call to implWrapper.A"
|
|
}
|
|
{
|
|
i := Impl{}
|
|
// This is an OCONVNOP, so we have to be careful, not to devirtualize it to Impl.A.
|
|
var a A = (implWrapper)(i) // ERROR "implWrapper\(i\) does not escape$"
|
|
a.A() // ERROR "devirtualizing a.A to implWrapper$" "inlining call to implWrapper.A"
|
|
}
|
|
{
|
|
type anyWrapper any
|
|
var foo any = &Impl{} // ERROR "&Impl\{\} does not escape"
|
|
var bar anyWrapper = foo
|
|
bar.(M).M() // ERROR "devirtualizing bar\.\(M\).M to \*Impl" "inlining call to \(\*Impl\)\.M"
|
|
}
|
|
}
|
|
|
|
func selfAssigns() {
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = a
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape"
|
|
var asAny any = a
|
|
asAny = asAny
|
|
asAny.(A).A() // ERROR "devirtualizing asAny.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape"
|
|
var asAny any = a
|
|
a = asAny.(A)
|
|
asAny.(A).A() // ERROR "devirtualizing asAny.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
a.(A).A() // ERROR "devirtualizing a.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
b := a
|
|
b.(A).A() // ERROR "devirtualizing b.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape"
|
|
var asAny any = a
|
|
asAny = asAny
|
|
a = asAny.(A)
|
|
asAny = a
|
|
asAny.(A).A() // ERROR "devirtualizing asAny.\(A\).A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
asAny.(M).M() // ERROR "devirtualizing asAny.\(M\).M to \*Impl$" "inlining call to \(\*Impl\).M"
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} does not escape"
|
|
var asAny A = a
|
|
a = asAny.(A)
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
{
|
|
var a, b, c A
|
|
c = &Impl{} // ERROR "&Impl{} does not escape$"
|
|
a = c
|
|
c = b
|
|
b = c
|
|
a = b
|
|
b = a
|
|
c = a
|
|
a.A() // ERROR "devirtualizing a.A to \*Impl$" "inlining call to \(\*Impl\).A"
|
|
}
|
|
}
|
|
|
|
func boolNoDevirt() {
|
|
{
|
|
m := make(map[int]*Impl) // ERROR "make\(map\[int\]\*Impl\) does not escape$"
|
|
var v any = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
_, v = m[0] // ERROR ".autotmp_[0-9]+ escapes to heap$"
|
|
v.(A).A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v any = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
select {
|
|
case _, v = <-m: // ERROR ".autotmp_[0-9]+ escapes to heap$"
|
|
}
|
|
v.(A).A()
|
|
}
|
|
{
|
|
m := make(chan *Impl)
|
|
var v any = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
_, v = <-m // ERROR ".autotmp_[0-9]+ escapes to heap$"
|
|
v.(A).A()
|
|
}
|
|
{
|
|
var a any = 4 // ERROR "4 does not escape$"
|
|
var v any = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
_, v = a.(int) // ERROR ".autotmp_[0-9]+ escapes to heap$"
|
|
v.(A).A()
|
|
}
|
|
}
|
|
|
|
func addrTaken() {
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var ptrA = &a
|
|
a.A()
|
|
_ = ptrA
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var ptrA = &a
|
|
*ptrA = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
{
|
|
var a A = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
var ptrA = &a
|
|
*ptrA = &Impl2{} // ERROR "&Impl2{} escapes to heap$"
|
|
a.A()
|
|
}
|
|
}
|
|
|
|
func testInvalidAsserts() {
|
|
any(0).(interface{ A() }).A() // ERROR "any\(0\) escapes to heap$"
|
|
{
|
|
var a M = &Impl{} // ERROR "&Impl{} escapes to heap$"
|
|
a.(C).C() // this will panic
|
|
a.(any).(C).C() // this will panic
|
|
}
|
|
{
|
|
var a C = &CImpl{} // ERROR "&CImpl{} escapes to heap$"
|
|
a.(M).M() // this will panic
|
|
a.(any).(M).M() // this will panic
|
|
}
|
|
{
|
|
var a C = &CImpl{} // ERROR "&CImpl{} does not escape$"
|
|
|
|
// this will panic
|
|
a.(M).(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
|
|
// this will panic
|
|
a.(any).(M).(*Impl).M() // ERROR "inlining call to \(\*Impl\).M"
|
|
}
|
|
}
|
|
|
|
type namedBool bool
|
|
|
|
func (namedBool) M() {} // ERROR "can inline namedBool.M$"
|
|
|
|
//go:noinline
|
|
func namedBoolTest() {
|
|
m := map[int]int{} // ERROR "map\[int\]int{} does not escape"
|
|
var ok namedBool
|
|
_, ok = m[5]
|
|
var i M = ok // ERROR "ok does not escape"
|
|
i.M() // ERROR "devirtualizing i.M to namedBool$" "inlining call to namedBool.M"
|
|
}
|