From 7e84666df17574adb0287aa2ae29769c71cd013e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 21 Jan 2011 18:15:59 -0500 Subject: [PATCH] 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 --- src/cmd/gc/typecheck.c | 48 +++++++++++++++++++++++++++++++++++------- test/cmp6.go | 7 ++++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 88e0fc0136..6711f69f5c 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -56,6 +56,34 @@ typechecklist(NodeList *l, int 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. * replaces *np with a new pointer in some cases. @@ -372,21 +400,25 @@ reswitch: et = t->etype; } if(t->etype != TIDEAL && !eqtype(l->type, r->type)) { - badbinary: 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; } - if(!okfor[op][et]) - goto badbinary; // okfor allows any array == array; // restrict to slice == nil and nil == slice. if(l->type->etype == TARRAY && !isslice(l->type)) - goto badbinary; + goto notokfor; if(r->type->etype == TARRAY && !isslice(r->type)) - goto badbinary; - if(isslice(l->type) && !isnil(l) && !isnil(r)) - goto badbinary; + goto notokfor; + if(isslice(l->type) && !isnil(l) && !isnil(r)) { + yyerror("invalid operation: %#N (slice can only be compared to nil)", n); + goto error; + } t = l->type; if(iscmp[n->op]) { evconst(n); diff --git a/test/cmp6.go b/test/cmp6.go index 981a859531..4c06011873 100644 --- a/test/cmp6.go +++ b/test/cmp6.go @@ -11,6 +11,10 @@ func use(bool) {} type T1 *int type T2 *int +type T3 struct {} + +var t3 T3 + func main() { // Arguments to comparison must be // assignable one to the other (or vice versa) @@ -39,4 +43,7 @@ func main() { use(p2 == p2) use(p3 == p1) use(p3 == p2) + + // Comparison of structs should have a good message + use(t3 == t3) // ERROR "struct" }