mirror of https://github.com/golang/go.git
go/types: convert untyped switch expressions to default type
R=1.6 Fixes #11667. Fixes #11687. Change-Id: I060db212e8e0ee35fdefb4d482398f8f71650b38 Reviewed-on: https://go-review.googlesource.com/12713 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
cb867d2fd6
commit
f1b5bb9588
|
|
@ -1462,9 +1462,9 @@ func (check *Checker) expr(x *operand, e ast.Expr) {
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
// exprWithHint typechecks expression e and initializes x with the expression value.
|
// exprWithHint typechecks expression e and initializes x with the expression value;
|
||||||
|
// hint is the type of a composite literal element.
|
||||||
// If an error occurred, x.mode is set to invalid.
|
// If an error occurred, x.mode is set to invalid.
|
||||||
// If hint != nil, it is the type of a composite literal element.
|
|
||||||
//
|
//
|
||||||
func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
|
func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
|
||||||
assert(hint != nil)
|
assert(hint != nil)
|
||||||
|
|
|
||||||
|
|
@ -155,25 +155,20 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
|
||||||
check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
|
check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) caseValues(x operand /* copy argument (not *operand!) */, values []ast.Expr) {
|
func (check *Checker) caseValues(x *operand, values []ast.Expr) {
|
||||||
// No duplicate checking for now. See issue 4524.
|
// No duplicate checking for now. See issue 4524.
|
||||||
for _, e := range values {
|
for _, e := range values {
|
||||||
var y operand
|
var v operand
|
||||||
check.expr(&y, e)
|
check.expr(&v, e)
|
||||||
if y.mode == invalid {
|
if x.mode == invalid || v.mode == invalid {
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
|
check.convertUntyped(&v, x.typ)
|
||||||
// Order matters: By comparing y against x, error positions are at the case values.
|
if v.mode == invalid {
|
||||||
check.convertUntyped(&y, x.typ)
|
continue
|
||||||
if y.mode == invalid {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
check.convertUntyped(&x, y.typ)
|
// Order matters: By comparing v against x, error positions are at the case values.
|
||||||
if x.mode == invalid {
|
check.comparison(&v, x, token.EQL)
|
||||||
return
|
|
||||||
}
|
|
||||||
check.comparison(&y, &x, token.EQL)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -399,6 +394,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||||
var x operand
|
var x operand
|
||||||
if s.Tag != nil {
|
if s.Tag != nil {
|
||||||
check.expr(&x, s.Tag)
|
check.expr(&x, s.Tag)
|
||||||
|
// By checking assignment of x to an invisible temporary
|
||||||
|
// (as a compiler would), we get all the relevant checks.
|
||||||
|
check.assignment(&x, nil)
|
||||||
} else {
|
} else {
|
||||||
// spec: "A missing switch expression is
|
// spec: "A missing switch expression is
|
||||||
// equivalent to the boolean value true."
|
// equivalent to the boolean value true."
|
||||||
|
|
@ -416,9 +414,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||||
check.invalidAST(c.Pos(), "incorrect expression switch case")
|
check.invalidAST(c.Pos(), "incorrect expression switch case")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if x.mode != invalid {
|
check.caseValues(&x, clause.List)
|
||||||
check.caseValues(x, clause.List)
|
|
||||||
}
|
|
||||||
check.openScope(clause, "case")
|
check.openScope(clause, "case")
|
||||||
inner := inner
|
inner := inner
|
||||||
if i+1 < len(s.Body.List) {
|
if i+1 < len(s.Body.List) {
|
||||||
|
|
|
||||||
|
|
@ -512,6 +512,65 @@ func switches1() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func switches2() {
|
||||||
|
// untyped nil is not permitted as switch expression
|
||||||
|
switch nil /* ERROR "use of untyped nil" */ {
|
||||||
|
case 1, 2, "foo": // don't report additional errors here
|
||||||
|
}
|
||||||
|
|
||||||
|
// untyped constants are converted to default types
|
||||||
|
switch 1<<63-1 {
|
||||||
|
}
|
||||||
|
switch 1 /* ERROR "overflows int" */ << 63 {
|
||||||
|
}
|
||||||
|
var x int
|
||||||
|
switch 1.0 {
|
||||||
|
case 1.0, 2.0, x /* ERROR "mismatched types int and float64" */ :
|
||||||
|
}
|
||||||
|
switch x {
|
||||||
|
case 1.0:
|
||||||
|
}
|
||||||
|
|
||||||
|
// untyped bools become of type bool
|
||||||
|
type B bool
|
||||||
|
var b B = true
|
||||||
|
switch x == x {
|
||||||
|
case b /* ERROR "mismatched types B and bool" */ :
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case b /* ERROR "mismatched types B and bool" */ :
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func issue11667() {
|
||||||
|
switch 9223372036854775808 /* ERROR "overflows int" */ {
|
||||||
|
}
|
||||||
|
switch 9223372036854775808 /* ERROR "overflows int" */ {
|
||||||
|
case 9223372036854775808:
|
||||||
|
}
|
||||||
|
var x int
|
||||||
|
switch x {
|
||||||
|
case 9223372036854775808 /* ERROR "overflows int" */ :
|
||||||
|
}
|
||||||
|
var y float64
|
||||||
|
switch y {
|
||||||
|
case 9223372036854775808:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func issue11687() {
|
||||||
|
f := func() (_, _ int) { return }
|
||||||
|
switch f /* ERROR "2-valued expression" */ () {
|
||||||
|
}
|
||||||
|
var x int
|
||||||
|
switch f /* ERROR "2-valued expression" */ () {
|
||||||
|
case x:
|
||||||
|
}
|
||||||
|
switch x {
|
||||||
|
case f /* ERROR "cannot compare" */ (): // TODO(gri) better error message (issue 11896)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type I interface {
|
type I interface {
|
||||||
m()
|
m()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue