diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 2b8134a02c..004630236d 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -26,12 +26,6 @@ import ( "cmd/internal/src" ) -// TODO(mdempsky): Suppress duplicate type/const errors that can arise -// during typecheck due to naive type substitution (e.g., see #42758). -// I anticipate these will be handled as a consequence of adding -// dictionaries support, so it's probably not important to focus on -// this until after that's done. - type pkgReader struct { pkgbits.PkgDecoder diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index fbe7c02c49..3be3b8059f 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -16,7 +16,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" - "cmd/internal/src" ) func roundFloat(v constant.Value, sz int64) constant.Value { @@ -773,94 +772,6 @@ func anyCallOrChan(n ir.Node) bool { }) } -// A constSet represents a set of Go constant expressions. -type constSet struct { - m map[constSetKey]src.XPos -} - -type constSetKey struct { - typ *types.Type - val interface{} -} - -// add adds constant expression n to s. If a constant expression of -// equal value and identical type has already been added, then add -// reports an error about the duplicate value. -// -// pos provides position information for where expression n occurred -// (in case n does not have its own position information). what and -// where are used in the error message. -// -// n must not be an untyped constant. -func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) { - if conv := n; conv.Op() == ir.OCONVIFACE { - conv := conv.(*ir.ConvExpr) - if conv.Implicit() { - n = conv.X - } - } - - if !ir.IsConstNode(n) || n.Type() == nil { - return - } - if n.Type().IsUntyped() { - base.Fatalf("%v is untyped", n) - } - - // Consts are only duplicates if they have the same value and - // identical types. - // - // In general, we have to use types.Identical to test type - // identity, because == gives false negatives for anonymous - // types and the byte/uint8 and rune/int32 builtin type - // aliases. However, this is not a problem here, because - // constant expressions are always untyped or have a named - // type, and we explicitly handle the builtin type aliases - // below. - // - // This approach may need to be revisited though if we fix - // #21866 by treating all type aliases like byte/uint8 and - // rune/int32. - - typ := n.Type() - switch typ { - case types.ByteType: - typ = types.Types[types.TUINT8] - case types.RuneType: - typ = types.Types[types.TINT32] - } - k := constSetKey{typ, ir.ConstValue(n)} - - if ir.HasUniquePos(n) { - pos = n.Pos() - } - - if s.m == nil { - s.m = make(map[constSetKey]src.XPos) - } - - if prevPos, isDup := s.m[k]; isDup { - base.ErrorfAt(pos, "duplicate %s %s in %s\n\tprevious %s at %v", - what, nodeAndVal(n), where, - what, base.FmtPos(prevPos)) - } else { - s.m[k] = pos - } -} - -// nodeAndVal reports both an expression and its constant value, if -// the latter is non-obvious. -// -// TODO(mdempsky): This could probably be a fmt.go flag. -func nodeAndVal(n ir.Node) string { - show := fmt.Sprint(n) - val := ir.ConstValue(n) - if s := fmt.Sprintf("%#v", val); show != s { - show += " (value " + s + ")" - } - return show -} - // evalunsafe evaluates a package unsafe operation and returns the result. func evalunsafe(n ir.Node) int64 { switch n.Op() { diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 0fe8f91696..e2b95b27c6 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -245,7 +245,6 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { n.Len = length case types.TMAP: - var cs constSet for i3, l := range n.List { ir.SetPos(l) if l.Op() != ir.OKEY { @@ -259,7 +258,6 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { r = pushtype(r, t.Key()) r = Expr(r) l.Key = AssignConv(r, t.Key(), "map key") - cs.add(base.Pos, l.Key, "key", "map literal") r = l.Value r = pushtype(r, t.Elem()) diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index f266007507..b2fba315e7 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -519,7 +519,6 @@ func tcSwitchExpr(n *ir.SwitchStmt) { } var defCase ir.Node - var cs constSet for _, ncase := range n.Cases { ls := ncase.List if len(ls) == 0 { // default: @@ -554,16 +553,6 @@ func tcSwitchExpr(n *ir.SwitchStmt) { } } } - - // Don't check for duplicate bools. Although the spec allows it, - // (1) the compiler hasn't checked it in the past, so compatibility mandates it, and - // (2) it would disallow useful things like - // case GOARCH == "arm" && GOARM == "5": - // case GOARCH == "arm": - // which would both evaluate to false for non-ARM compiles. - if !n1.Type().IsBoolean() { - cs.add(ncase.Pos(), n1, "case", "switch") - } } Stmts(ncase.Body) diff --git a/test/typeparam/issue42758.go b/test/typeparam/issue42758.go new file mode 100644 index 0000000000..25fb85ffb6 --- /dev/null +++ b/test/typeparam/issue42758.go @@ -0,0 +1,19 @@ +// 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. + +package main + +func F[T, U int]() interface{} { + switch interface{}(nil) { + case int(0), T(0), U(0): + } + + return map[interface{}]int{int(0): 0, T(0): 0, U(0): 0} +} + +func main() { + F[int, int]() +}