]> Cypherpunks repositories - gostls13.git/commitdiff
gc: clearer error for struct == struct
authorRuss Cox <rsc@golang.org>
Fri, 21 Jan 2011 23:15:59 +0000 (18:15 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 21 Jan 2011 23:15:59 +0000 (18:15 -0500)
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
test/cmp6.go

index 88e0fc0136e1abb48efbf3699d8b364c38c5cb66..6711f69f5c6c816ce8885c48a41ea942449bfebc 100644 (file)
@@ -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);
index 981a85953171a39b185f46996d61a781b355a229..4c06011873154640517caf52ed81cec8801b6179 100644 (file)
@@ -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"
 }