diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index fe8f8f2a351..8fed138a4a1 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1582,6 +1582,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 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) @@ -1603,6 +1604,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 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) @@ -1655,12 +1657,18 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { // 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 + } } } } @@ -1696,7 +1704,11 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 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) } } diff --git a/test/fixedbugs/issue67190.go b/test/fixedbugs/issue67190.go new file mode 100644 index 00000000000..c19b248b51c --- /dev/null +++ b/test/fixedbugs/issue67190.go @@ -0,0 +1,24 @@ +// 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") + } +}