]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: suppress typecheck errors in a type switch case with broken type
authorGergely Brautigam <skarlso777@gmail.com>
Fri, 18 Jan 2019 20:43:56 +0000 (21:43 +0100)
committerDaniel Martí <mvdan@mvdan.cc>
Wed, 27 Feb 2019 08:22:03 +0000 (08:22 +0000)
If a type switch case expression has failed typechecking, the case body is
likely to also fail with confusing or spurious errors. Suppress
typechecking the case body when this happens.

Fixes #28926

Change-Id: Idfdb9d5627994f2fd90154af1659e9a92bf692c4
Reviewed-on: https://go-review.googlesource.com/c/158617
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/swt.go
test/fixedbugs/issue28926.go [new file with mode: 0644]

index 70fc66bf574c5701e7e1b43de91b41c6acbc3eb4..6a418859541e44ef6b00074c9083b4b8721031a4 100644 (file)
@@ -184,18 +184,11 @@ func typecheckswitch(n *Node) {
                        }
                }
 
-               if n.Type == nil || n.Type.IsUntyped() {
-                       // if the value we're switching on has no type or is untyped,
-                       // we've already printed an error and don't need to continue
-                       // typechecking the body
-                       return
-               }
-
                if top == Etype {
                        ll := ncase.List
                        if ncase.Rlist.Len() != 0 {
                                nvar := ncase.Rlist.First()
-                               if ll.Len() == 1 && ll.First().Type != nil && !ll.First().Type.IsKind(TNIL) {
+                               if ll.Len() == 1 && (ll.First().Type == nil || !ll.First().Type.IsKind(TNIL)) {
                                        // single entry type switch
                                        nvar.Type = ll.First().Type
                                } else {
@@ -203,6 +196,13 @@ func typecheckswitch(n *Node) {
                                        nvar.Type = n.Type
                                }
 
+                               if nvar.Type == nil || nvar.Type.IsUntyped() {
+                                       // if the value we're switching on has no type or is untyped,
+                                       // we've already printed an error and don't need to continue
+                                       // typechecking the body
+                                       continue
+                               }
+
                                nvar = typecheck(nvar, ctxExpr|ctxAssign)
                                ncase.Rlist.SetFirst(nvar)
                        }
diff --git a/test/fixedbugs/issue28926.go b/test/fixedbugs/issue28926.go
new file mode 100644 (file)
index 0000000..5a46bd3
--- /dev/null
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2018 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 main
+
+type Stringer interface {
+       String() string
+}
+
+func main() {
+       var e interface{}
+       switch e := e.(type) {
+       case G: // ERROR "undefined: G"
+               e.M() // ok: this error should be ignored because the case failed its typecheck
+       case E: // ERROR "undefined: E"
+               e.D() // ok: this error should be ignored because the case failed its typecheck
+       case Stringer:
+               // ok: this error should not be ignored to prove that passing legs aren't left out
+               _ = e.(T) // ERROR "undefined: T"
+       }
+}