}
}
+// isNil reports whether the expression e denotes the predeclared value nil.
+func (check *Checker) isNil(e syntax.Expr) bool {
+ // The only way to express the nil value is by literally writing nil (possibly in parentheses).
+ if name, _ := unparen(e).(*syntax.Name); name != nil {
+ _, ok := check.lookup(name.Value).(*Nil)
+ return ok
+ }
+ return false
+}
+
func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
+ var dummy operand
L:
for _, e := range types {
- T = check.typOrNil(e)
- if T == Typ[Invalid] {
- continue L
- }
- if T != nil {
- check.ordinaryType(e.Pos(), T)
+ // The spec allows the value nil instead of a type.
+ if check.isNil(e) {
+ T = nil
+ check.expr(&dummy, e) // run e through expr so we get the usual Info recordings
+ } else {
+ T = check.varType(e)
+ if T == Typ[Invalid] {
+ continue L
+ }
}
// look for duplicate types
// (quadratic algorithm, but type switches tend to be reasonably small)
--- /dev/null
+// Copyright 2021 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
+
+type T[P any] struct{}
+
+func _(x interface{}) {
+ switch x.(type) {
+ case nil:
+ case int:
+
+ case T[int]:
+ case []T[int]:
+ case [10]T[int]:
+ case struct{T[int]}:
+ case *T[int]:
+ case func(T[int]):
+ case interface{m(T[int])}:
+ case map[T[int]] string:
+ case chan T[int]:
+
+ case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ :
+ case []T /* ERROR cannot use generic type */ :
+ case [10]T /* ERROR cannot use generic type */ :
+ case struct{T /* ERROR cannot use generic type */ }:
+ case *T /* ERROR cannot use generic type */ :
+ case func(T /* ERROR cannot use generic type */ ):
+ case interface{m(T /* ERROR cannot use generic type */ )}:
+ case map[T /* ERROR cannot use generic type */ ] string:
+ case chan T /* ERROR cannot use generic type */ :
+
+ case T /* ERROR cannot use generic type */ , *T /* ERROR cannot use generic type */ :
+ }
+}
+
+// Make sure a parenthesized nil is ok.
+
+func _(x interface{}) {
+ switch x.(type) {
+ case ((nil)), int:
+ }
+}
+
+// Make sure we look for the predeclared nil.
+
+func _(x interface{}) {
+ type nil int
+ switch x.(type) {
+ case nil: // ok - this is the type nil
+ }
+}
+
+func _(x interface{}) {
+ var nil int
+ switch x.(type) {
+ case nil /* ERROR not a type */ : // not ok - this is the variable nil
+ }
+}
return typ
}
-// typeOrNil type-checks the type expression (or nil value) e
-// and returns the type of e, or nil. If e is a type, it must
-// not be an (uninstantiated) generic type.
-// If e is neither a type nor nil, typeOrNil returns Typ[Invalid].
-// TODO(gri) should we also disallow non-var types?
-func (check *Checker) typOrNil(e syntax.Expr) Type {
- var x operand
- check.rawExpr(&x, e, nil)
- switch x.mode {
- case invalid:
- // ignore - error reported before
- case novalue:
- check.errorf(&x, "%s used as type", &x)
- case typexpr:
- check.instantiatedOperand(&x)
- return x.typ
- case nilvalue:
- return nil
- default:
- check.errorf(&x, "%s is not a type", &x)
- }
- return Typ[Invalid]
-}
-
func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) Type {
gtyp := check.genericType(x, true)
if gtyp == Typ[Invalid] {
}
}
+// isNil reports whether the expression e denotes the predeclared value nil.
+func (check *Checker) isNil(e ast.Expr) bool {
+ // The only way to express the nil value is by literally writing nil (possibly in parentheses).
+ if name, _ := unparen(e).(*ast.Ident); name != nil {
+ _, ok := check.lookup(name.Name).(*Nil)
+ return ok
+ }
+ return false
+}
+
func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
+ var dummy operand
L:
for _, e := range types {
- T = check.typeOrNil(e)
- if T == Typ[Invalid] {
- continue L
- }
- if T != nil {
- check.ordinaryType(e, T)
+ // The spec allows the value nil instead of a type.
+ if check.isNil(e) {
+ T = nil
+ check.expr(&dummy, e) // run e through expr so we get the usual Info recordings
+ } else {
+ T = check.varType(e)
+ if T == Typ[Invalid] {
+ continue L
+ }
}
// look for duplicate types
// (quadratic algorithm, but type switches tend to be reasonably small)
--- /dev/null
+// Copyright 2021 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
+
+type T[P any] struct{}
+
+func _(x interface{}) {
+ switch x.(type) {
+ case nil:
+ case int:
+
+ case T[int]:
+ case []T[int]:
+ case [10]T[int]:
+ case struct{T[int]}:
+ case *T[int]:
+ case func(T[int]):
+ case interface{m(T[int])}:
+ case map[T[int]] string:
+ case chan T[int]:
+
+ case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ :
+ case []T /* ERROR cannot use generic type */ :
+ case [10]T /* ERROR cannot use generic type */ :
+ case struct{T /* ERROR cannot use generic type */ }:
+ case *T /* ERROR cannot use generic type */ :
+ case func(T /* ERROR cannot use generic type */ ):
+ case interface{m(T /* ERROR cannot use generic type */ )}:
+ case map[T /* ERROR cannot use generic type */ ] string:
+ case chan T /* ERROR cannot use generic type */ :
+
+ case T /* ERROR cannot use generic type */ , *T /* ERROR cannot use generic type */ :
+ }
+}
+
+// Make sure a parenthesized nil is ok.
+
+func _(x interface{}) {
+ switch x.(type) {
+ case ((nil)), int:
+ }
+}
+
+// Make sure we look for the predeclared nil.
+
+func _(x interface{}) {
+ type nil int
+ switch x.(type) {
+ case nil: // ok - this is the type nil
+ }
+}
+
+func _(x interface{}) {
+ var nil int
+ switch x.(type) {
+ case nil /* ERROR not a type */ : // not ok - this is the variable nil
+ }
+}
return typ
}
-// typeOrNil type-checks the type expression (or nil value) e
-// and returns the type of e, or nil. If e is a type, it must
-// not be an (uninstantiated) generic type.
-// If e is neither a type nor nil, typeOrNil returns Typ[Invalid].
-// TODO(gri) should we also disallow non-var types?
-func (check *Checker) typeOrNil(e ast.Expr) Type {
- var x operand
- check.rawExpr(&x, e, nil)
- switch x.mode {
- case invalid:
- // ignore - error reported before
- case novalue:
- check.errorf(&x, _NotAType, "%s used as type", &x)
- case typexpr:
- check.instantiatedOperand(&x)
- return x.typ
- case value:
- if x.isNil() {
- return nil
- }
- fallthrough
- default:
- check.errorf(&x, _NotAType, "%s is not a type", &x)
- }
- return Typ[Invalid]
-}
-
func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type {
gtyp := check.genericType(x, true)
if gtyp == Typ[Invalid] {