aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2020-11-24 22:07:04 -0800
committerRobert Griesemer <gri@golang.org>2020-11-25 17:16:04 +0000
commit2c25cd5ba7772a97ee63787e3986b6ec231e8c3d (patch)
tree55a5ea98a8731ef5a098b2ffc1069b110a2e6c5c
parent0fb733b7f79001092897282749bf5942953b0675 (diff)
downloadgo-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.go20
-rw-r--r--src/cmd/compile/internal/types2/fixedbugs/issue42758.go233
-rw-r--r--src/cmd/compile/internal/types2/stmt.go17
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 {