go/types: report error for invalid (but empty) expr switch

This is a port of CL 278132 from the dev.typeparams branch. A notable
addition is a new error code, since no existing codes made sense and we
have an analogous code for type switches.

Fixes #43110

Change-Id: I22b3f9d8777063223f82785504e8b7d299bc5216
Reviewed-on: https://go-review.googlesource.com/c/go/+/278813
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Robert Findley <rfindley@google.com>
This commit is contained in:
Rob Findley 2020-12-16 17:19:44 -05:00 committed by Robert Findley
parent 5abda2618b
commit b0f01e17f8
3 changed files with 57 additions and 0 deletions

View file

@ -1207,6 +1207,16 @@ const (
// }
_InvalidTypeSwitch
// _InvalidExprSwitch occurs when a switch expression is not comparable.
//
// Example:
// func _() {
// var a struct{ _ func() }
// switch a /* ERROR cannot switch on a */ {
// }
// }
_InvalidExprSwitch
/* control flow > select */
// _InvalidSelectCase occurs when a select case is not a channel send or

View file

@ -0,0 +1,43 @@
// 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
type P *struct{}
func _() {
// want an error even if the switch is empty
var a struct{ _ func() }
switch a /* ERROR cannot switch on a */ {
}
switch a /* ERROR cannot switch on a */ {
case a: // no follow-on error here
}
// this is ok because f can be compared to nil
var f func()
switch f {
}
switch f {
case nil:
}
switch (func())(nil) {
case nil:
}
switch (func())(nil) {
case f /* ERROR cannot compare */ :
}
switch nil /* ERROR use of untyped nil in switch expression */ {
}
// this is ok
switch P(nil) {
case P(nil):
}
}

View file

@ -528,6 +528,10 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// By checking assignment of x to an invisible temporary
// (as a compiler would), we get all the relevant checks.
check.assignment(&x, nil, "switch expression")
if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
check.errorf(&x, _InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
x.mode = invalid
}
} else {
// spec: "A missing switch expression is
// equivalent to the boolean value true."