mirror of
https://github.com/golang/go
synced 2024-11-11 22:20:22 -07:00
[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>
This commit is contained in:
parent
0fb733b7f7
commit
2c25cd5ba7
@ -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
|
||||
|
||||
|
33
src/cmd/compile/internal/types2/fixedbugs/issue42758.go2
Normal file
33
src/cmd/compile/internal/types2/fixedbugs/issue42758.go2
Normal file
@ -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) {
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user