Commit f1b5bb95 authored by Robert Griesemer's avatar Robert Griesemer

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/12713Reviewed-by: default avatarAlan Donovan <adonovan@google.com>
parent cb867d2f
...@@ -1462,9 +1462,9 @@ func (check *Checker) expr(x *operand, e ast.Expr) { ...@@ -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) { ...@@ -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!
// Order matters: By comparing y against x, error positions are at the case values.
check.convertUntyped(&y, x.typ)
if y.mode == invalid {
return
} }
check.convertUntyped(&x, y.typ) check.convertUntyped(&v, x.typ)
if x.mode == invalid { if v.mode == invalid {
return continue
} }
check.comparison(&y, &x, token.EQL) // Order matters: By comparing v against x, error positions are at the case values.
check.comparison(&v, x, token.EQL)
} }
} }
...@@ -399,6 +394,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { ...@@ -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) { ...@@ -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() { ...@@ -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()
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment