Commit f4f1ba2b authored by Rémy Oudompheng's avatar Rémy Oudompheng

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
parent 728f1913
......@@ -813,7 +813,7 @@ typecheckswitch(Node *n)
{
int top, lno, ptr;
char *nilonly;
Type *t, *missing, *have;
Type *t, *badtype, *missing, *have;
NodeList *l, *ll;
Node *ncase, *nvar;
Node *def;
......@@ -839,10 +839,14 @@ typecheckswitch(Node *n)
} else
t = types[TBOOL];
if(t) {
if(!okforeq[t->etype] || isfixedarray(t))
if(!okforeq[t->etype])
yyerror("cannot switch on %lN", n->ntest);
else if(t->etype == TARRAY)
else if(t->etype == TARRAY && !isfixedarray(t))
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)
nilonly = "func";
else if(t->etype == TMAP)
......
......@@ -284,6 +284,38 @@ func main() {
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
switch x := 5; {
case i < x:
......
......@@ -45,6 +45,17 @@ func bad() {
case f1: // ERROR "can only compare func f to nil|func can only be compared to nil"
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() {
......
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