go.tools/go/types: no duplicate checking in expr switches for now

See also issue 4524.

R=adonovan
CC=golang-dev
https://golang.org/cl/16700045
This commit is contained in:
Robert Griesemer 2013-10-24 14:02:14 -07:00
parent ad46727525
commit c20165988a
4 changed files with 32 additions and 47 deletions

View File

@ -190,4 +190,3 @@ func Implements(V Type, T *Interface, static bool) bool {
}
// BUG(gri): Interface vs non-interface comparisons are not correctly implemented.
// BUG(gri): Switch statements don't check duplicate cases for all types for which it is required.

View File

@ -119,7 +119,6 @@ func TestStdtest(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
"sizeof.go", "switch.go", // TODO(gri) tone down duplicate checking in expr switches
"typeswitch2.go", // TODO(gri) implement duplicate checking in type switches
)
}
@ -127,7 +126,7 @@ func TestStdtest(t *testing.T) {
func TestStdfixed(t *testing.T) {
testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
"bug165.go", // TODO(gri) isComparable not working for incomplete struct type
"bug200.go", // TODO(gri) complete duplicate checking in expr switches
"bug200.go", // TODO(gri) complete duplicate checking in type switches
"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)

View File

@ -99,6 +99,28 @@ 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) {
// No duplicate checking for now. See issue 4524.
for _, e := range values {
var y operand
check.expr(&y, e)
if y.mode == invalid {
return
}
// 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)
if x.mode == invalid {
return
}
check.comparison(&y, &x, token.EQL)
}
}
// stmt typechecks statement s.
func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
// statements cannot use iota in general
@ -296,53 +318,15 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
check.expr(&x, tag)
check.multipleDefaults(s.Body.List)
// TODO(gri) check also correct use of fallthrough
seen := make(map[interface{}]token.Pos)
for i, c := range s.Body.List {
clause, _ := c.(*ast.CaseClause)
if clause == nil {
continue // error reported before
check.invalidAST(c.Pos(), "incorrect expression switch case")
continue
}
if x.mode != invalid {
for _, expr := range clause.List {
x := x // copy of x (don't modify original)
var y operand
check.expr(&y, expr)
if y.mode == invalid {
continue // error reported before
}
// If we have a constant case value, it must appear only
// once in the switch statement. Determine if there is a
// duplicate entry, but only report an error if there are
// no other errors.
var dupl token.Pos
var yy operand
if y.mode == constant {
// TODO(gri) This code doesn't work correctly for
// large integer, floating point, or
// complex values - the respective struct
// comparisons are shallow. Need to use a
// hash function to index the map.
dupl = seen[y.val]
seen[y.val] = y.pos()
yy = y // remember y
}
// 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 {
continue // error reported before
}
check.convertUntyped(&x, y.typ)
if x.mode == invalid {
continue // error reported before
}
check.comparison(&y, &x, token.EQL)
if y.mode != invalid && dupl.IsValid() {
check.errorf(yy.pos(), "%s is duplicate case (previous at %s)",
&yy, check.fset.Position(dupl))
}
}
check.caseValues(x, clause.List)
}
check.openScope(clause)
inner := inner
@ -411,6 +395,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
}
check.multipleDefaults(s.Body.List)
var lhsVars []*Var // set of implicitly declared lhs variables
for _, s := range s.Body.List {
clause, _ := s.(*ast.CaseClause)
@ -459,7 +444,9 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
case *ast.SelectStmt:
inner |= inBreakable
check.multipleDefaults(s.Body.List)
for _, s := range s.Body.List {
clause, _ := s.(*ast.CommClause)
if clause == nil {

View File

@ -361,9 +361,9 @@ func switches0() {
switch x {
case 1:
case 1 /* ERROR "duplicate case" */ :
case 1 /* DISABLED "duplicate case" */ :
case 2, 3, 4:
case 1 /* ERROR "duplicate case" */ :
case 1 /* DISABLED "duplicate case" */ :
}
// TODO(gri) duplicate 64bit values that don't fit into an int64 are not yet detected