summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/escape_iface.go10
-rw-r--r--test/escape_iface_nounified.go25
-rw-r--r--test/escape_iface_unified.go24
-rw-r--r--test/fixedbugs/issue27836.dir/Äfoo.go13
-rw-r--r--test/fixedbugs/issue27836.dir/Ämain.go13
-rw-r--r--test/fixedbugs/issue27836.dir/Þfoo.go17
-rw-r--r--test/fixedbugs/issue27836.dir/Þmain.go17
-rw-r--r--test/fixedbugs/issue32187.go14
-rw-r--r--test/fixedbugs/issue42284.dir/b.go2
-rw-r--r--test/fixedbugs/issue52128.dir/a.go21
-rw-r--r--test/fixedbugs/issue52128.dir/b.go17
-rw-r--r--test/fixedbugs/issue52128.dir/p.go14
-rw-r--r--test/fixedbugs/issue52128.go7
-rw-r--r--test/fixedbugs/issue7921.go2
-rw-r--r--test/inline.go12
-rw-r--r--test/inline_nounified.go21
-rw-r--r--test/inline_unified.go21
-rw-r--r--test/live_regabi.go3
-rw-r--r--test/nilcheck.go3
-rw-r--r--test/run.go23
-rw-r--r--test/switch.go14
-rw-r--r--test/typeparam/mdempsky/16.go34
-rw-r--r--test/typeparam/mdempsky/17.go110
-rw-r--r--test/typeparam/mdempsky/18.go26
-rw-r--r--test/typeparam/mdempsky/18.out1
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