[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>
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index e166e99..cb92143 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1703,22 +1703,12 @@
 		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 @@
 		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 0000000..698cb8a
--- /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 d88f65b..37aa3c7 100644
--- a/src/cmd/compile/internal/types2/stmt.go
+++ b/src/cmd/compile/internal/types2/stmt.go
@@ -666,19 +666,12 @@
 	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 @@
 		}
 		// 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 {