mirror of
https://github.com/golang/go
synced 2024-11-21 18:04:40 -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:
parent
9e441e5215
commit
7e84666df1
@ -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);
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user