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
|
||||
}
|
||||
|
||||
// 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 hint != nil, it is the type of a composite literal element.
|
||||
//
|
||||
func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
|
||||
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)
|
||||
}
|
||||
|
||||
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.
|
||||
for _, e := range values {
|
||||
var y operand
|
||||
check.expr(&y, e)
|
||||
if y.mode == invalid {
|
||||
return
|
||||
var v operand
|
||||
check.expr(&v, e)
|
||||
if x.mode == invalid || v.mode == invalid {
|
||||
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(&v, x.typ)
|
||||
if v.mode == invalid {
|
||||
continue
|
||||
}
|
||||
check.convertUntyped(&x, y.typ)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
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) {
|
|||
var x operand
|
||||
if s.Tag != nil {
|
||||
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 {
|
||||
// spec: "A missing switch expression is
|
||||
// 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")
|
||||
continue
|
||||
}
|
||||
if x.mode != invalid {
|
||||
check.caseValues(x, clause.List)
|
||||
}
|
||||
check.caseValues(&x, clause.List)
|
||||
check.openScope(clause, "case")
|
||||
inner := inner
|
||||
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 {
|
||||
m()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue