mirror of
https://github.com/golang/go
synced 2024-11-22 00:44:39 -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:
parent
728f191319
commit
f4f1ba2b1e
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user