diff options
Diffstat (limited to 'test')
25 files changed, 392 insertions, 72 deletions
diff --git a/test/escape_iface.go b/test/escape_iface.go index dba08e3cb3..986228129a 100644 --- a/test/escape_iface.go +++ b/test/escape_iface.go @@ -235,16 +235,6 @@ func dotTypeEscape2() { // #13805, #15796 *(&v), *(&ok) = y.(int) } { - i := 0 - j := 0 - var ok bool - var x interface{} = i // ERROR "i does not escape" - var y interface{} = j // ERROR "j does not escape" - - sink = x.(int) // ERROR "x.\(int\) escapes to heap" - sink, *(&ok) = y.(int) - } - { i := 0 // ERROR "moved to heap: i" j := 0 // ERROR "moved to heap: j" var ok bool diff --git a/test/escape_iface_nounified.go b/test/escape_iface_nounified.go new file mode 100644 index 0000000000..1d267bcd18 --- /dev/null +++ b/test/escape_iface_nounified.go @@ -0,0 +1,25 @@ +// errorcheck -0 -m -l +//go:build !goexperiment.unified +// +build !goexperiment.unified + +// Copyright 2015 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 + +var sink interface{} + +func dotTypeEscape2() { // #13805, #15796 + { + i := 0 + j := 0 + var ok bool + var x interface{} = i // ERROR "i does not escape" + var y interface{} = j // ERROR "j does not escape" + + sink = x.(int) // ERROR "x.\(int\) escapes to heap" + // BAD: should be "y.\(int\) escapes to heap" too + sink, *(&ok) = y.(int) + } +} diff --git a/test/escape_iface_unified.go b/test/escape_iface_unified.go new file mode 100644 index 0000000000..80222dae5f --- /dev/null +++ b/test/escape_iface_unified.go @@ -0,0 +1,24 @@ +// errorcheck -0 -m -l +//go:build goexperiment.unified +// +build goexperiment.unified + +// Copyright 2015 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 + +var sink interface{} + +func dotTypeEscape2() { // #13805, #15796 + { + i := 0 + j := 0 + var ok bool + var x interface{} = i // ERROR "i does not escape" + var y interface{} = j // ERROR "j does not escape" + + sink = x.(int) // ERROR "x.\(int\) escapes to heap" + sink, *(&ok) = y.(int) // ERROR "autotmp_.* escapes to heap" + } +} diff --git a/test/fixedbugs/issue27836.dir/Äfoo.go b/test/fixedbugs/issue27836.dir/Äfoo.go deleted file mode 100644 index 8b6a814c3c..0000000000 --- a/test/fixedbugs/issue27836.dir/Äfoo.go +++ /dev/null @@ -1,13 +0,0 @@ -package Äfoo - -var ÄbarV int = 101 - -func Äbar(x int) int { - defer func() { ÄbarV += 3 }() - return Äblix(x) -} - -func Äblix(x int) int { - defer func() { ÄbarV += 9 }() - return ÄbarV + x -} diff --git a/test/fixedbugs/issue27836.dir/Ämain.go b/test/fixedbugs/issue27836.dir/Ämain.go deleted file mode 100644 index 25d2c71fc0..0000000000 --- a/test/fixedbugs/issue27836.dir/Ämain.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "fmt" - - "./Äfoo" - Äblix "./Äfoo" -) - -func main() { - fmt.Printf("Äfoo.Äbar(33) returns %v\n", Äfoo.Äbar(33)) - fmt.Printf("Äblix.Äbar(33) returns %v\n", Äblix.Äbar(33)) -} diff --git a/test/fixedbugs/issue27836.dir/Þfoo.go b/test/fixedbugs/issue27836.dir/Þfoo.go new file mode 100644 index 0000000000..ea6be0f49f --- /dev/null +++ b/test/fixedbugs/issue27836.dir/Þfoo.go @@ -0,0 +1,17 @@ +// Copyright 2022 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 Þfoo + +var ÞbarV int = 101 + +func Þbar(x int) int { + defer func() { ÞbarV += 3 }() + return Þblix(x) +} + +func Þblix(x int) int { + defer func() { ÞbarV += 9 }() + return ÞbarV + x +} diff --git a/test/fixedbugs/issue27836.dir/Þmain.go b/test/fixedbugs/issue27836.dir/Þmain.go new file mode 100644 index 0000000000..596c620d80 --- /dev/null +++ b/test/fixedbugs/issue27836.dir/Þmain.go @@ -0,0 +1,17 @@ +// Copyright 2022 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 main + +import ( + "fmt" + + "./Þfoo" + Þblix "./Þfoo" +) + +func main() { + fmt.Printf("Þfoo.Þbar(33) returns %v\n", Þfoo.Þbar(33)) + fmt.Printf("Þblix.Þbar(33) returns %v\n", Þblix.Þbar(33)) +} diff --git a/test/fixedbugs/issue32187.go b/test/fixedbugs/issue32187.go index 9c8c9c26d7..268da8112f 100644 --- a/test/fixedbugs/issue32187.go +++ b/test/fixedbugs/issue32187.go @@ -36,7 +36,11 @@ func main() { {"type assertion", "", func() { _ = x == x.(*int) }}, {"out of bounds", "", func() { _ = x == s[1] }}, {"nil pointer dereference #1", "", func() { _ = x == *p }}, - {"nil pointer dereference #2", "nil pointer dereference", func() { _ = *l == r[0] }}, + // TODO(mdempsky): Restore "nil pointer dereference" check. The Go + // spec doesn't mandate an order for panics (or even panic + // messages), but left-to-right is less confusing to users. + {"nil pointer dereference #2", "", func() { _ = *l == r[0] }}, + {"nil pointer dereference #3", "", func() { _ = *l == any(r[0]) }}, } for _, tc := range tests { @@ -44,16 +48,14 @@ func main() { } } -func testFuncShouldPanic(name, errStr string, f func()) { +func testFuncShouldPanic(name, want string, f func()) { defer func() { e := recover() if e == nil { log.Fatalf("%s: comparison did not panic\n", name) } - if errStr != "" { - if !strings.Contains(e.(error).Error(), errStr) { - log.Fatalf("%s: wrong panic message\n", name) - } + if have := e.(error).Error(); !strings.Contains(have, want) { + log.Fatalf("%s: wrong panic message: have %q, want %q\n", name, have, want) } }() f() diff --git a/test/fixedbugs/issue42284.dir/b.go b/test/fixedbugs/issue42284.dir/b.go index 652aa32122..8cd93b8db4 100644 --- a/test/fixedbugs/issue42284.dir/b.go +++ b/test/fixedbugs/issue42284.dir/b.go @@ -7,7 +7,7 @@ package b import "./a" func g() { - h := a.E() // ERROR "inlining call to a.E" "a.I\(a.T\(0\)\) does not escape" + h := a.E() // ERROR "inlining call to a.E" "T\(0\) does not escape" h.M() // ERROR "devirtualizing h.M to a.T" // BAD: T(0) could be stack allocated. diff --git a/test/fixedbugs/issue52128.dir/a.go b/test/fixedbugs/issue52128.dir/a.go new file mode 100644 index 0000000000..0abf831c6f --- /dev/null +++ b/test/fixedbugs/issue52128.dir/a.go @@ -0,0 +1,21 @@ +// Copyright 2022 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 a + +type I interface{} + +type F func() + +type s struct { + f F +} + +func NewWithF(f F) *s { + return &s{f: f} +} + +func NewWithFuncI(func() I) *s { + return &s{} +} diff --git a/test/fixedbugs/issue52128.dir/b.go b/test/fixedbugs/issue52128.dir/b.go new file mode 100644 index 0000000000..86f6ed7e05 --- /dev/null +++ b/test/fixedbugs/issue52128.dir/b.go @@ -0,0 +1,17 @@ +// Copyright 2022 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 b + +import ( + "./a" +) + +type S struct{} + +func (s *S) M1() a.I { + return a.NewWithF(s.M2) +} + +func (s *S) M2() {} diff --git a/test/fixedbugs/issue52128.dir/p.go b/test/fixedbugs/issue52128.dir/p.go new file mode 100644 index 0000000000..d3f3dbbfb9 --- /dev/null +++ b/test/fixedbugs/issue52128.dir/p.go @@ -0,0 +1,14 @@ +// Copyright 2022 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 p + +import ( + "./a" + "./b" +) + +func f() { + a.NewWithFuncI((&b.S{}).M1) +} diff --git a/test/fixedbugs/issue52128.go b/test/fixedbugs/issue52128.go new file mode 100644 index 0000000000..8bb5c3e213 --- /dev/null +++ b/test/fixedbugs/issue52128.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2022 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 ignored diff --git a/test/fixedbugs/issue7921.go b/test/fixedbugs/issue7921.go index 65be4b5bbe..f9efb7f55d 100644 --- a/test/fixedbugs/issue7921.go +++ b/test/fixedbugs/issue7921.go @@ -41,7 +41,7 @@ func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$" func bufferNoEscape4() []byte { var b bytes.Buffer - b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m\]$" "inlining call to bytes.\(\*Buffer\).Grow$" "string\(.*\) escapes to heap" + b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m\]$" "inlining call to bytes.\(\*Buffer\).Grow$" `".+" escapes to heap` useBuffer(&b) return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$" } diff --git a/test/inline.go b/test/inline.go index 400898bcee..04ba16858f 100644 --- a/test/inline.go +++ b/test/inline.go @@ -107,18 +107,6 @@ func q(x int) int { // ERROR "can inline q" return foo() // ERROR "inlining call to q.func1" } -func r(z int) int { - foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape" - return x + z - } - bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2" - return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3" - return 2*y + x*z - }(x) // ERROR "inlining call to r.func2.1" - } - return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3" -} - func s0(x int) int { // ERROR "can inline s0" foo := func() { // ERROR "can inline s0.func1" "func literal does not escape" x = x + 1 diff --git a/test/inline_nounified.go b/test/inline_nounified.go new file mode 100644 index 0000000000..7a9fc10071 --- /dev/null +++ b/test/inline_nounified.go @@ -0,0 +1,21 @@ +// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 +//go:build !goexperiment.unified +// +build !goexperiment.unified + +// Copyright 2022 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 foo + +func r(z int) int { + foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape" + return x + z + } + bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2" + return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3" + return 2*y + x*z + }(x) // ERROR "inlining call to r.func2.1" + } + return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3" +} diff --git a/test/inline_unified.go b/test/inline_unified.go new file mode 100644 index 0000000000..ff70e44151 --- /dev/null +++ b/test/inline_unified.go @@ -0,0 +1,21 @@ +// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 +//go:build goexperiment.unified +// +build goexperiment.unified + +// Copyright 2022 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 foo + +func r(z int) int { + foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape" + return x + z + } + bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2" + return x + func(y int) int { // ERROR "can inline r.func2.1" + return 2*y + x*z + }(x) // ERROR "inlining call to r.func2.1" + } + return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "can inline r.func3" "inlining call to r.func3" +} diff --git a/test/live_regabi.go b/test/live_regabi.go index aac9a7766c..59be1863fc 100644 --- a/test/live_regabi.go +++ b/test/live_regabi.go @@ -1,4 +1,5 @@ // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off +//go:build (amd64 && goexperiment.regabiargs) || (arm64 && goexperiment.regabiargs) // +build amd64,goexperiment.regabiargs arm64,goexperiment.regabiargs // Copyright 2014 The Go Authors. All rights reserved. @@ -601,7 +602,7 @@ func f38(b bool) { printnl() case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$" printnl() - case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" + case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$" printnl() } printnl() diff --git a/test/nilcheck.go b/test/nilcheck.go index 6879438e9c..e81db6dcb0 100644 --- a/test/nilcheck.go +++ b/test/nilcheck.go @@ -184,6 +184,7 @@ func f4(x *[10]int) { func f5(m map[string]struct{}) bool { // Existence-only map lookups should not generate a nil check - _, ok := m[""] + tmp1, tmp2 := m[""] // ERROR "removed nil check" + _, ok := tmp1, tmp2 return ok } diff --git a/test/run.go b/test/run.go index b2902f190c..4a99203761 100644 --- a/test/run.go +++ b/test/run.go @@ -1980,8 +1980,11 @@ var types2Failures32Bit = setOf( ) var go118Failures = setOf( - "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics - "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error + "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics + "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error + "typeparam/mdempsky/16.go", // 1.18 compiler uses interface shape type in failed type assertions + "typeparam/mdempsky/17.go", // 1.18 compiler mishandles implicit conversions from range loops + "typeparam/mdempsky/18.go", // 1.18 compiler mishandles implicit conversions in select statements ) // In all of these cases, the 1.17 compiler reports reasonable errors, but either the @@ -2009,18 +2012,10 @@ var _ = setOf( ) var unifiedFailures = setOf( - "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures - "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this - "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures - "linkname3.go", // unified IR is missing some linkname errors - - "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" - "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" - "typeparam/issue47631.go", // unified IR can handle local type declarations - "fixedbugs/issue42058a.go", // unified IR doesn't report channel element too large - "fixedbugs/issue42058b.go", // unified IR doesn't report channel element too large - "fixedbugs/issue49767.go", // unified IR doesn't report channel element too large - "fixedbugs/issue49814.go", // unified IR doesn't report array type too large + "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures + "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this + + "typeparam/issue47631.go", // unified IR can handle local type declarations ) func setOf(keys ...string) map[string]bool { diff --git a/test/switch.go b/test/switch.go index 5e1d85bb68..1806fa7f9b 100644 --- a/test/switch.go +++ b/test/switch.go @@ -400,4 +400,18 @@ func main() { case i > x: os.Exit(1) } + + // Unified IR converts the tag and all case values to empty + // interface, when any of the case values aren't assignable to the + // tag value's type. Make sure that `case nil:` compares against the + // tag type's nil value (i.e., `(*int)(nil)`), not nil interface + // (i.e., `any(nil)`). + switch (*int)(nil) { + case nil: + // ok + case any(nil): + assert(false, "case any(nil) matched") + default: + assert(false, "default matched") + } } diff --git a/test/typeparam/mdempsky/16.go b/test/typeparam/mdempsky/16.go new file mode 100644 index 0000000000..f4f79b9aac --- /dev/null +++ b/test/typeparam/mdempsky/16.go @@ -0,0 +1,34 @@ +// run + +// Copyright 2022 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 that type assertion panics mention the real interface type, +// not their shape type. + +package main + +import ( + "fmt" + "runtime" + "strings" +) + +func main() { + // The exact error message isn't important, but it should mention + // `main.T`, not `go.shape.int_0`. + if have := F[T](); !strings.Contains(have, "interface { T() main.T }") { + fmt.Printf("FAIL: unexpected panic message: %q\n", have) + } +} + +type T int + +func F[T any]() (res string) { + defer func() { + res = recover().(runtime.Error).Error() + }() + _ = interface{ T() T }(nil).(T) + return +} diff --git a/test/typeparam/mdempsky/17.go b/test/typeparam/mdempsky/17.go new file mode 100644 index 0000000000..12385c3f9e --- /dev/null +++ b/test/typeparam/mdempsky/17.go @@ -0,0 +1,110 @@ +// run + +// Copyright 2022 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 that implicit conversions of derived types to interface type +// in range loops work correctly. + +package main + +import ( + "fmt" + "reflect" +) + +func main() { + test{"int", "V"}.match(RangeArrayAny[V]()) + test{"int", "V"}.match(RangeArrayIface[V]()) + test{"V"}.match(RangeChanAny[V]()) + test{"V"}.match(RangeChanIface[V]()) + test{"K", "V"}.match(RangeMapAny[K, V]()) + test{"K", "V"}.match(RangeMapIface[K, V]()) + test{"int", "V"}.match(RangeSliceAny[V]()) + test{"int", "V"}.match(RangeSliceIface[V]()) +} + +type test []string + +func (t test) match(args ...any) { + if len(t) != len(args) { + fmt.Printf("FAIL: want %v values, have %v\n", len(t), len(args)) + return + } + for i, want := range t { + if have := reflect.TypeOf(args[i]).Name(); want != have { + fmt.Printf("FAIL: %v: want type %v, have %v\n", i, want, have) + } + } +} + +type iface interface{ M() int } + +type K int +type V int + +func (K) M() int { return 0 } +func (V) M() int { return 0 } + +func RangeArrayAny[V any]() (k, v any) { + for k, v = range [...]V{zero[V]()} { + } + return +} + +func RangeArrayIface[V iface]() (k any, v iface) { + for k, v = range [...]V{zero[V]()} { + } + return +} + +func RangeChanAny[V any]() (v any) { + for v = range chanOf(zero[V]()) { + } + return +} + +func RangeChanIface[V iface]() (v iface) { + for v = range chanOf(zero[V]()) { + } + return +} + +func RangeMapAny[K comparable, V any]() (k, v any) { + for k, v = range map[K]V{zero[K](): zero[V]()} { + } + return +} + +func RangeMapIface[K interface { + iface + comparable +}, V iface]() (k, v iface) { + for k, v = range map[K]V{zero[K](): zero[V]()} { + } + return +} + +func RangeSliceAny[V any]() (k, v any) { + for k, v = range []V{zero[V]()} { + } + return +} + +func RangeSliceIface[V iface]() (k any, v iface) { + for k, v = range []V{zero[V]()} { + } + return +} + +func chanOf[T any](elems ...T) chan T { + c := make(chan T, len(elems)) + for _, elem := range elems { + c <- elem + } + close(c) + return c +} + +func zero[T any]() (_ T) { return } diff --git a/test/typeparam/mdempsky/18.go b/test/typeparam/mdempsky/18.go new file mode 100644 index 0000000000..f4a4ec73c5 --- /dev/null +++ b/test/typeparam/mdempsky/18.go @@ -0,0 +1,26 @@ +// run + +// Copyright 2022 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 that implicit conversions to interface type in a select/case +// clause are compiled correctly. + +package main + +import "fmt" + +func main() { f[int]() } + +func f[T any]() { + ch := make(chan T) + close(ch) + + var i, ok any + select { + case i, ok = <-ch: + } + + fmt.Printf("%T %T\n", i, ok) +} diff --git a/test/typeparam/mdempsky/18.out b/test/typeparam/mdempsky/18.out new file mode 100644 index 0000000000..19f1c39a22 --- /dev/null +++ b/test/typeparam/mdempsky/18.out @@ -0,0 +1 @@ +int bool |