aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2024-06-25 02:35:19 +0700
committerGopher Robot <gobot@golang.org>2024-07-03 18:07:19 +0000
commit5f50b1e3bf710b4107eb38496d932b3d9bd1fc98 (patch)
tree2ebd14064679c2dbd46a0a538fc851b105776920 /src/cmd/compile/internal/noder
parent71f9dbb1e409a28680f40c60fad5a386ed92a096 (diff)
downloadgo-5f50b1e3bf710b4107eb38496d932b3d9bd1fc98.tar.xz
cmd/compile: fix mis-compilation when switching over channels
CL 418101 changes Unified IR writer to force mixed tag/case to have common type, emitting the implicit conversion if any of the case values are not assignable to the tag value's type. However, the Go spec definition of equality is non-transitive for channels stored in interfaces, causing incorrect behavior with channel values comparison. To fix it, don't emit the implicit conversions if tag type is channel. Fixes #67190 Change-Id: I9a29d9ce3c7978f0689e9502ba6f15660c763d16 Reviewed-on: https://go-review.googlesource.com/c/go/+/594575 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/writer.go26
1 files changed, 19 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index fe8f8f2a35..8fed138a4a 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)
}
}