diff options
author | Robert Griesemer <gri@golang.org> | 2020-11-24 22:07:04 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2020-11-25 17:16:04 +0000 |
commit | 2c25cd5ba7772a97ee63787e3986b6ec231e8c3d (patch) | |
tree | 55a5ea98a8731ef5a098b2ffc1069b110a2e6c5c | |
parent | 0fb733b7f79001092897282749bf5942953b0675 (diff) | |
download | go-2c25cd5ba7772a97ee63787e3986b6ec231e8c3d.tar.gz go-2c25cd5ba7772a97ee63787e3986b6ec231e8c3d.zip |
[dev.typeparams] cmd/compile/internal/types2: a type parameter is a valid type case in a type switch
Likewise for type assertions.
This is a port of https://golang.org/cl/273127 to dev.typeparams.
Updates #42758.
Change-Id: If93246371c3555e067b0043f0caefaac99101ebc
Reviewed-on: https://go-review.googlesource.com/c/go/+/273128
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
-rw-r--r-- | src/cmd/compile/internal/types2/expr.go | 20 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/fixedbugs/issue42758.go2 | 33 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/stmt.go | 17 |
3 files changed, 43 insertions, 27 deletions
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index e166e9926c..cb92143f93 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1703,22 +1703,12 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin if x.mode == invalid { goto Error } - var xtyp *Interface - var strict bool - switch t := optype(x.typ.Under()).(type) { - case *Interface: - xtyp = t - // Disabled for now. It is not clear what the right approach is - // here. Also, the implementation below is inconsistent because - // the underlying type of a type parameter is either itself or - // a sum type if the corresponding type bound contains a type list. - // case *TypeParam: - // xtyp = t.Bound() - // strict = true - default: - check.invalidOpf(x, "%s is not an interface type", x) + xtyp, _ := x.typ.Under().(*Interface) + if xtyp == nil { + check.errorf(x, "%s is not an interface type", x) goto Error } + check.ordinaryType(x.Pos(), xtyp) // x.(type) expressions are encoded via TypeSwitchGuards if e.Type == nil { check.invalidASTf(e, "invalid use of AssertExpr") @@ -1728,7 +1718,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin if T == Typ[Invalid] { goto Error } - check.typeAssertion(posFor(x), x, xtyp, T, strict) + check.typeAssertion(posFor(x), x, xtyp, T, false) x.mode = commaok x.typ = T diff --git a/src/cmd/compile/internal/types2/fixedbugs/issue42758.go2 b/src/cmd/compile/internal/types2/fixedbugs/issue42758.go2 new file mode 100644 index 0000000000..698cb8a16b --- /dev/null +++ b/src/cmd/compile/internal/types2/fixedbugs/issue42758.go2 @@ -0,0 +1,33 @@ +// Copyright 2020 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 + +func _[T any](x interface{}){ + switch x.(type) { + case T: // ok to use a type parameter + case int: + } + + switch x.(type) { + case T: + case T /* ERROR duplicate case */ : + } +} + +type constraint interface { + type int +} + +func _[T constraint](x interface{}){ + switch x.(type) { + case T: // ok to use a type parameter even if type list contains int + case int: + } +} + +func _(x constraint /* ERROR contains type constraints */ ) { + switch x /* ERROR contains type constraints */ .(type) { + } +} diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index d88f65b15e..37aa3c7308 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -666,19 +666,12 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu if x.mode == invalid { return } - var xtyp *Interface - var strict bool - switch t := x.typ.Under().(type) { - case *Interface: - xtyp = t - // Disabled for now. See comment in the implementation of type assertions (expr.go). - // case *TypeParam: - // xtyp = t.Bound() - // strict = true - default: - check.errorf(&x, "%s is not an interface or generic type", &x) + xtyp, _ := x.typ.Under().(*Interface) + if xtyp == nil { + check.errorf(&x, "%s is not an interface type", &x) return } + check.ordinaryType(x.Pos(), xtyp) check.multipleSwitchDefaults(s.Body) @@ -691,7 +684,7 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu } // Check each type in this type switch case. cases := unpackExpr(clause.Cases) - T := check.caseTypes(&x, xtyp, cases, seen, strict) + T := check.caseTypes(&x, xtyp, cases, seen, false) check.openScope(clause, "case") // If lhs exists, declare a corresponding variable in the case-local scope. if lhs != nil { |