]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: a type parameter is a valid type case...
authorRobert Griesemer <gri@golang.org>
Wed, 25 Nov 2020 06:07:04 +0000 (22:07 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 25 Nov 2020 17:16:04 +0000 (17:16 +0000)
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>
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/fixedbugs/issue42758.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/stmt.go

index e166e9926c7a833815706abf35fe87018fd7082c..cb92143f93676976c2c5ae9747efcb9ba4e70183 100644 (file)
@@ -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 (file)
index 0000000..698cb8a
--- /dev/null
@@ -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) {
+       }
+}
index d88f65b15e438aed61faf765a04cc2359ecb832e..37aa3c730856ba890e14296c3002e0bc5b8c0643 100644 (file)
@@ -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 {