]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: report error for invalid (but empty) expr switch
authorRob Findley <rfindley@google.com>
Wed, 16 Dec 2020 22:19:44 +0000 (17:19 -0500)
committerRobert Findley <rfindley@google.com>
Wed, 16 Dec 2020 22:45:19 +0000 (22:45 +0000)
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>

src/go/types/errorcodes.go
src/go/types/fixedbugs/issue43110.src [new file with mode: 0644]
src/go/types/stmt.go

index e4c8311d62e42b2491647b00fb53a3568bef0371..c01a12c346d3e50c301e589e3fd2a762664a6593 100644 (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
diff --git a/src/go/types/fixedbugs/issue43110.src b/src/go/types/fixedbugs/issue43110.src
new file mode 100644 (file)
index 0000000..4a46945
--- /dev/null
@@ -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):
+       }
+}
index 7b3f322ced2c5763597d110ae607edbf094d57bf..d88e47170c3a676b3ffa83acebb82a27fbb0e5cf 100644 (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."