mirror of
https://github.com/golang/go
synced 2024-11-17 07:24:53 -07:00
1129a60f1c
Include type information on exported function bodies, so that the importer does not have to re-typecheck the body. This involves including type information in the encoded output, as well as avoiding some of the opcode rewriting and other changes that the old exporter did assuming there would be a re-typechecking pass. This CL could be considered a cleanup, but is more important than that because it is an enabling change for generics. Without this CL, we'd have to upgrade the current typechecker to understand generics. With this CL, the current typechecker can mostly go away in favor of the types2 typechecker. For now, inlining of functions that contain closures is turned off. We will hopefully resolve this before freeze. Object files are only 0.07% bigger. Change-Id: I85c9da09f66bfdc910dc3e26abb2613a1831634d Reviewed-on: https://go-review.googlesource.com/c/go/+/301291 Trust: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Dan Scales <danscales@google.com>
290 lines
6.8 KiB
Go
290 lines
6.8 KiB
Go
// Copyright 2017 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.
|
|
|
|
// Check correctness of various closure corner cases
|
|
// that are expected to be inlined
|
|
|
|
package main
|
|
|
|
var ok bool
|
|
var sink int
|
|
|
|
func main() {
|
|
{
|
|
if x := func() int { // ERROR "can inline main.func1"
|
|
return 1
|
|
}(); x != 1 { // ERROR "inlining call to main.func1"
|
|
ppanic("x != 1")
|
|
}
|
|
if x := func() int { // ERROR "can inline main.func2" "func literal does not escape"
|
|
return 1
|
|
}; x() != 1 { // ERROR "inlining call to main.func2"
|
|
ppanic("x() != 1")
|
|
}
|
|
}
|
|
|
|
{
|
|
if y := func(x int) int { // ERROR "can inline main.func3"
|
|
return x + 2
|
|
}(40); y != 42 { // ERROR "inlining call to main.func3"
|
|
ppanic("y != 42")
|
|
}
|
|
if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
|
|
return x + 2
|
|
}; y(40) != 42 { // ERROR "inlining call to main.func4"
|
|
ppanic("y(40) != 42")
|
|
}
|
|
}
|
|
|
|
{
|
|
y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape"
|
|
return x + 1
|
|
}
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}
|
|
|
|
{
|
|
func() { // ERROR "func literal does not escape"
|
|
y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape"
|
|
return x + 1
|
|
}
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}()
|
|
}
|
|
|
|
{
|
|
y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape"
|
|
return x + 1
|
|
}, 42
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}
|
|
|
|
{
|
|
func() { // ERROR "func literal does not escape"
|
|
y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape"
|
|
return x + 1
|
|
}, 42
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}()
|
|
}
|
|
|
|
{
|
|
y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
|
|
return func(x int) int { // ERROR "can inline main.func12" "func literal escapes"
|
|
return x + 1
|
|
}, 42
|
|
}()
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}
|
|
|
|
{
|
|
func() { // ERROR "func literal does not escape"
|
|
y := func(x int) int { // ERROR "can inline main.func13.1" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
|
|
return func(x int) int { // ERROR "can inline main.func13.2" "func literal escapes"
|
|
return x + 1
|
|
}, 42
|
|
}()
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}()
|
|
}
|
|
|
|
{
|
|
y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, ok = map[int]func(int) int{ // ERROR "does not escape"
|
|
0: func(x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
|
|
}[0]
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}
|
|
|
|
{
|
|
func() { // ERROR "func literal does not escape"
|
|
y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, ok = map[int]func(int) int{ // ERROR "does not escape"
|
|
0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
|
|
}[0]
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}()
|
|
}
|
|
|
|
{
|
|
y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, ok = interface{}(func(x int) int { // ERROR "can inline main.func18" "does not escape"
|
|
return x + 1
|
|
}).(func(int) int)
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}
|
|
|
|
{
|
|
func() { // ERROR "func literal does not escape"
|
|
y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape"
|
|
return x + 2
|
|
}
|
|
y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape"
|
|
return x + 1
|
|
}).(func(int) int)
|
|
if y(40) != 41 {
|
|
ppanic("y(40) != 41")
|
|
}
|
|
}()
|
|
}
|
|
|
|
{
|
|
x := 42
|
|
if y := func() int { // ERROR "can inline main.func20"
|
|
return x
|
|
}(); y != 42 { // ERROR "inlining call to main.func20"
|
|
ppanic("y != 42")
|
|
}
|
|
if y := func() int { // ERROR "can inline main.func21" "func literal does not escape"
|
|
return x
|
|
}; y() != 42 { // ERROR "inlining call to main.func21"
|
|
ppanic("y() != 42")
|
|
}
|
|
}
|
|
|
|
{
|
|
x := 42
|
|
if z := func(y int) int { // ERROR "func literal does not escape"
|
|
return func() int { // ERROR "can inline main.func22.1"
|
|
return x + y
|
|
}() // ERROR "inlining call to main.func22.1"
|
|
}(1); z != 43 {
|
|
ppanic("z != 43")
|
|
}
|
|
if z := func(y int) int { // ERROR "func literal does not escape"
|
|
return func() int { // ERROR "can inline main.func23.1"
|
|
return x + y
|
|
}() // ERROR "inlining call to main.func23.1"
|
|
}; z(1) != 43 {
|
|
ppanic("z(1) != 43")
|
|
}
|
|
}
|
|
|
|
{
|
|
a := 1
|
|
func() { // ERROR "func literal does not escape"
|
|
func() { // ERROR "can inline main.func24"
|
|
a = 2
|
|
}() // ERROR "inlining call to main.func24"
|
|
}()
|
|
if a != 2 {
|
|
ppanic("a != 2")
|
|
}
|
|
}
|
|
|
|
{
|
|
b := 2
|
|
func(b int) { // ERROR "func literal does not escape"
|
|
func() { // ERROR "can inline main.func25.1"
|
|
b = 3
|
|
}() // ERROR "inlining call to main.func25.1"
|
|
if b != 3 {
|
|
ppanic("b != 3")
|
|
}
|
|
}(b)
|
|
if b != 2 {
|
|
ppanic("b != 2")
|
|
}
|
|
}
|
|
|
|
{
|
|
c := 3
|
|
func() { // ERROR "func literal does not escape"
|
|
c = 4
|
|
func() { // ERROR "func literal does not escape"
|
|
if c != 4 {
|
|
ppanic("c != 4")
|
|
}
|
|
recover() // prevent inlining
|
|
}()
|
|
}()
|
|
if c != 4 {
|
|
ppanic("c != 4")
|
|
}
|
|
}
|
|
|
|
{
|
|
a := 2
|
|
if r := func(x int) int { // ERROR "func literal does not escape"
|
|
b := 3
|
|
return func(y int) int { // ERROR "func literal does not escape"
|
|
c := 5
|
|
return func(z int) int { // ERROR "can inline main.func27.1.1"
|
|
return a*x + b*y + c*z
|
|
}(10) // ERROR "inlining call to main.func27.1.1"
|
|
}(100)
|
|
}(1000); r != 2350 {
|
|
ppanic("r != 2350")
|
|
}
|
|
}
|
|
|
|
{
|
|
a := 2
|
|
if r := func(x int) int { // ERROR "func literal does not escape"
|
|
b := 3
|
|
return func(y int) int { // ERROR "func literal does not escape"
|
|
c := 5
|
|
func(z int) { // ERROR "can inline main.func28.1.1"
|
|
a = a * x
|
|
b = b * y
|
|
c = c * z
|
|
}(10) // ERROR "inlining call to main.func28.1.1"
|
|
return a + c
|
|
}(100) + b
|
|
}(1000); r != 2350 {
|
|
ppanic("r != 2350")
|
|
}
|
|
if a != 2000 {
|
|
ppanic("a != 2000")
|
|
}
|
|
}
|
|
}
|
|
|
|
//go:noinline
|
|
func ppanic(s string) { // ERROR "leaking param: s"
|
|
panic(s) // ERROR "s escapes to heap"
|
|
}
|