go/types, types2: better error msg when using fallthrough in type switch

Fixes #51533.

Change-Id: Ia41a2e96d1ef94f740887e3167e6396e4f52035c
Reviewed-on: https://go-review.googlesource.com/c/go/+/392759
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2022-03-14 14:05:53 -07:00
parent efbff6e43b
commit 5df3f491ac
6 changed files with 67 additions and 12 deletions

View file

@ -95,6 +95,7 @@ const (
// additional context information
finalSwitchCase
inTypeSwitch
)
func (check *Checker) simpleStmt(s syntax.Stmt) {
@ -370,7 +371,9 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
// process collected function literals before scope changes
defer check.processDelayed(len(check.delayed))
inner := ctxt &^ (fallthroughOk | finalSwitchCase)
// reset context for statements of inner blocks
inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
switch s := s.(type) {
case *syntax.EmptyStmt:
// ignore
@ -523,9 +526,14 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
}
case syntax.Fallthrough:
if ctxt&fallthroughOk == 0 {
msg := "fallthrough statement out of place"
if ctxt&finalSwitchCase != 0 {
var msg string
switch {
case ctxt&finalSwitchCase != 0:
msg = "cannot fallthrough final case in switch"
case ctxt&inTypeSwitch != 0:
msg = "cannot fallthrough in type switch"
default:
msg = "fallthrough statement out of place"
}
check.error(s, msg)
}
@ -572,7 +580,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
check.simpleStmt(s.Init)
if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
check.typeSwitchStmt(inner, s, g)
check.typeSwitchStmt(inner|inTypeSwitch, s, g)
} else {
check.switchStmt(inner, s)
}

View file

@ -542,7 +542,7 @@ func switches1() {
var y interface{}
switch y.(type) {
case int:
fallthrough /* ERROR "fallthrough statement out of place" */ ; ; ;
fallthrough /* ERROR "cannot fallthrough in type switch" */ ; ; ;
default:
}

View file

@ -0,0 +1,20 @@
// Copyright 2022 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 _(x any) {
switch x {
case 0:
fallthrough // ERROR fallthrough statement out of place
_ = x
default:
}
switch x.(type) {
case int:
fallthrough // ERROR cannot fallthrough in type switch
default:
}
}

View file

@ -96,6 +96,7 @@ const (
// additional context information
finalSwitchCase
inTypeSwitch
)
func (check *Checker) simpleStmt(s ast.Stmt) {
@ -375,7 +376,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// process collected function literals before scope changes
defer check.processDelayed(len(check.delayed))
inner := ctxt &^ (fallthroughOk | finalSwitchCase)
// reset context for statements of inner blocks
inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
switch s := s.(type) {
case *ast.BadStmt, *ast.EmptyStmt:
// ignore
@ -541,12 +544,16 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
}
case token.FALLTHROUGH:
if ctxt&fallthroughOk == 0 {
msg := "fallthrough statement out of place"
code := _MisplacedFallthrough
if ctxt&finalSwitchCase != 0 {
var msg string
switch {
case ctxt&finalSwitchCase != 0:
msg = "cannot fallthrough final case in switch"
case ctxt&inTypeSwitch != 0:
msg = "cannot fallthrough in type switch"
default:
msg = "fallthrough statement out of place"
}
check.error(s, code, msg)
check.error(s, _MisplacedFallthrough, msg)
}
default:
check.invalidAST(s, "branch statement: %s", s.Tok)
@ -627,7 +634,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
}
case *ast.TypeSwitchStmt:
inner |= breakOk
inner |= breakOk | inTypeSwitch
check.openScope(s, "type switch")
defer check.closeScope()

View file

@ -542,7 +542,7 @@ func switches1() {
var y interface{}
switch y.(type) {
case int:
fallthrough /* ERROR "fallthrough statement out of place" */ ; ; ;
fallthrough /* ERROR "cannot fallthrough in type switch" */ ; ; ;
default:
}

View file

@ -0,0 +1,20 @@
// Copyright 2022 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 _(x any) {
switch x {
case 0:
fallthrough // ERROR fallthrough statement out of place
_ = x
default:
}
switch x.(type) {
case int:
fallthrough // ERROR cannot fallthrough in type switch
default:
}
}