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

gc: clearer error for struct == struct

cmp6.go:48: invalid operation: t3 == t3 (operator == not defined on struct)

Fixes #1438.

R=ken2
CC=golang-dev
https://golang.org/cl/4003045
This commit is contained in:
Russ Cox 2011-01-21 18:15:59 -05:00
parent 9e441e5215
commit 7e84666df1
2 changed files with 47 additions and 8 deletions

View File

@ -56,6 +56,34 @@ typechecklist(NodeList *l, int top)
typecheck(&l->n, top); typecheck(&l->n, top);
} }
static char* typekind[] = {
[TINT] = "int",
[TUINT] = "uint",
[TINT8] = "int8",
[TUINT8] = "uint8",
[TINT16] = "int16",
[TUINT16] = "uint16",
[TINT32] = "int32",
[TUINT32] = "uint32",
[TINT64] = "int64",
[TUINT64] = "uint64",
[TUINTPTR] = "uintptr",
[TCOMPLEX64] = "complex64",
[TCOMPLEX128] = "complex128",
[TFLOAT32] = "float32",
[TFLOAT64] = "float64",
[TBOOL] = "bool",
[TSTRING] = "string",
[TPTR32] = "pointer",
[TPTR64] = "pointer",
[TSTRUCT] = "struct",
[TINTER] = "interface",
[TCHAN] = "chan",
[TMAP] = "map",
[TARRAY] = "array",
[TFUNC] = "func",
};
/* /*
* type check node *np. * type check node *np.
* replaces *np with a new pointer in some cases. * replaces *np with a new pointer in some cases.
@ -372,21 +400,25 @@ reswitch:
et = t->etype; et = t->etype;
} }
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) { if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
badbinary:
defaultlit2(&l, &r, 1); defaultlit2(&l, &r, 1);
yyerror("invalid operation: %#N (type %T %#O %T)", n, l->type, op, r->type); yyerror("invalid operation: %#N (mismatched types %T and %T)", n, l->type, r->type);
goto error;
}
if(!okfor[op][et]) {
notokfor:
yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind[et]);
goto error; goto error;
} }
if(!okfor[op][et])
goto badbinary;
// okfor allows any array == array; // okfor allows any array == array;
// restrict to slice == nil and nil == slice. // restrict to slice == nil and nil == slice.
if(l->type->etype == TARRAY && !isslice(l->type)) if(l->type->etype == TARRAY && !isslice(l->type))
goto badbinary; goto notokfor;
if(r->type->etype == TARRAY && !isslice(r->type)) if(r->type->etype == TARRAY && !isslice(r->type))
goto badbinary; goto notokfor;
if(isslice(l->type) && !isnil(l) && !isnil(r)) if(isslice(l->type) && !isnil(l) && !isnil(r)) {
goto badbinary; yyerror("invalid operation: %#N (slice can only be compared to nil)", n);
goto error;
}
t = l->type; t = l->type;
if(iscmp[n->op]) { if(iscmp[n->op]) {
evconst(n); evconst(n);

View File

@ -11,6 +11,10 @@ func use(bool) {}
type T1 *int type T1 *int
type T2 *int type T2 *int
type T3 struct {}
var t3 T3
func main() { func main() {
// Arguments to comparison must be // Arguments to comparison must be
// assignable one to the other (or vice versa) // assignable one to the other (or vice versa)
@ -39,4 +43,7 @@ func main() {
use(p2 == p2) use(p2 == p2)
use(p3 == p1) use(p3 == p1)
use(p3 == p2) use(p3 == p2)
// Comparison of structs should have a good message
use(t3 == t3) // ERROR "struct"
} }