w.stmt(stmt.Init)
var iface, tagType types2.Type
+ var tagTypeIsChan bool
if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
iface = w.p.typeOf(guard.X)
tv := w.p.typeAndValue(tag)
tagType = tv.Type
tagValue = tv.Value
+ _, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
} else {
tagType = types2.Typ[types2.Bool]
tagValue = constant.MakeBool(true)
// have the same type. If there are any case values that can't be
// converted to the tag value's type, then convert everything to
// `any` instead.
- Outer:
- for _, clause := range stmt.Body {
- for _, cas := range syntax.UnpackListExpr(clause.Cases) {
- if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) {
- tagType = types2.NewInterfaceType(nil, nil)
- break Outer
+ //
+ // Except that we need to keep comparisons of channel values from
+ // being wrapped in any(). See issue #67190.
+
+ if !tagTypeIsChan {
+ Outer:
+ for _, clause := range stmt.Body {
+ for _, cas := range syntax.UnpackListExpr(clause.Cases) {
+ if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) {
+ tagType = types2.NewInterfaceType(nil, nil)
+ break Outer
+ }
}
}
}
w.Sync(pkgbits.SyncExprs)
w.Len(len(cases))
for _, cas := range cases {
- w.implicitConvExpr(tagType, cas)
+ typ := tagType
+ if tagTypeIsChan {
+ typ = nil
+ }
+ w.implicitConvExpr(typ, cas)
}
}
--- /dev/null
+// run
+
+// Copyright 2024 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
+
+func main() {
+ ch1 := make(chan struct{})
+ var ch2 <-chan struct{} = ch1
+
+ switch ch1 {
+ case ch2:
+ default:
+ panic("bad narrow case")
+ }
+
+ switch ch2 {
+ case ch1:
+ default:
+ panic("bad narrow switch")
+ }
+}