1
0
mirror of https://github.com/golang/go synced 2024-11-25 02:57:57 -07:00

cmd/gc: accept switches on comparable arrays.

The compiler is incorrectly rejecting switches on arrays of
comparable types. It also doesn't catch incomparable structs
when typechecking the switch, leading to unreadable errors
during typechecking of the generated code.

Fixes #3894.

R=rsc
CC=gobot, golang-dev, r, remy
https://golang.org/cl/6442074
This commit is contained in:
Rémy Oudompheng 2012-08-03 21:47:26 +02:00
parent 728f191319
commit f4f1ba2b1e
3 changed files with 50 additions and 3 deletions

View File

@ -813,7 +813,7 @@ typecheckswitch(Node *n)
{ {
int top, lno, ptr; int top, lno, ptr;
char *nilonly; char *nilonly;
Type *t, *missing, *have; Type *t, *badtype, *missing, *have;
NodeList *l, *ll; NodeList *l, *ll;
Node *ncase, *nvar; Node *ncase, *nvar;
Node *def; Node *def;
@ -839,10 +839,14 @@ typecheckswitch(Node *n)
} else } else
t = types[TBOOL]; t = types[TBOOL];
if(t) { if(t) {
if(!okforeq[t->etype] || isfixedarray(t)) if(!okforeq[t->etype])
yyerror("cannot switch on %lN", n->ntest); yyerror("cannot switch on %lN", n->ntest);
else if(t->etype == TARRAY) else if(t->etype == TARRAY && !isfixedarray(t))
nilonly = "slice"; nilonly = "slice";
else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ)
yyerror("cannot switch on %lN", n->ntest);
else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ)
yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype);
else if(t->etype == TFUNC) else if(t->etype == TFUNC)
nilonly = "func"; nilonly = "func";
else if(t->etype == TMAP) else if(t->etype == TMAP)

View File

@ -284,6 +284,38 @@ func main() {
default: default:
} }
// switch on interface.
switch i := interface{}("hello"); i {
case 42:
assert(false, `i should be "hello"`)
case "hello":
assert(true, "hello")
default:
assert(false, `i should be "hello"`)
}
// switch on array.
switch ar := [3]int{1, 2, 3}; ar {
case [3]int{1,2,3}:
assert(true, "[1 2 3]")
case [3]int{4,5,6}:
assert(false, "ar should be [1 2 3]")
default:
assert(false, "ar should be [1 2 3]")
}
// switch on channel
switch c1, c2 := make(chan int), make(chan int); c1 {
case nil:
assert(false, "c1 did not match itself")
case c2:
assert(false, "c1 did not match itself")
case c1:
assert(true, "chan")
default:
assert(false, "c1 did not match itself")
}
i := 0 i := 0
switch x := 5; { switch x := 5; {
case i < x: case i < x:

View File

@ -45,6 +45,17 @@ func bad() {
case f1: // ERROR "can only compare func f to nil|func can only be compared to nil" case f1: // ERROR "can only compare func f to nil|func can only be compared to nil"
default: default:
} }
var ar, ar1 [4]func()
switch ar { // ERROR "cannot switch on"
case ar1:
default:
}
var st, st1 struct{ f func() }
switch st { // ERROR "cannot switch on"
case st1:
}
} }
func good() { func good() {