mirror of
https://github.com/golang/go
synced 2024-11-11 19:41:36 -07:00
cmd/gc: fix comparison of struct with _ field
Fixes #2989. R=ken2 CC=golang-dev https://golang.org/cl/5674091
This commit is contained in:
parent
ce020ffacd
commit
c4c92ebeb6
@ -1172,6 +1172,7 @@ int implements(Type *t, Type *iface, Type **missing, Type **have, int *ptr);
|
|||||||
void importdot(Pkg *opkg, Node *pack);
|
void importdot(Pkg *opkg, Node *pack);
|
||||||
int is64(Type *t);
|
int is64(Type *t);
|
||||||
int isblank(Node *n);
|
int isblank(Node *n);
|
||||||
|
int isblanksym(Sym *s);
|
||||||
int isfixedarray(Type *t);
|
int isfixedarray(Type *t);
|
||||||
int isideal(Type *t);
|
int isideal(Type *t);
|
||||||
int isinter(Type *t);
|
int isinter(Type *t);
|
||||||
|
@ -571,6 +571,8 @@ algtype1(Type *t, Type **bad)
|
|||||||
}
|
}
|
||||||
ret = AMEM;
|
ret = AMEM;
|
||||||
for(t1=t->type; t1!=T; t1=t1->down) {
|
for(t1=t->type; t1!=T; t1=t1->down) {
|
||||||
|
if(isblanksym(t1->sym))
|
||||||
|
continue;
|
||||||
a = algtype1(t1->type, bad);
|
a = algtype1(t1->type, bad);
|
||||||
if(a == ANOEQ)
|
if(a == ANOEQ)
|
||||||
return ANOEQ; // not comparable
|
return ANOEQ; // not comparable
|
||||||
@ -887,12 +889,20 @@ isslice(Type *t)
|
|||||||
|
|
||||||
int
|
int
|
||||||
isblank(Node *n)
|
isblank(Node *n)
|
||||||
|
{
|
||||||
|
if(n == N)
|
||||||
|
return 0;
|
||||||
|
return isblanksym(n->sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isblanksym(Sym *s)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if(n == N || n->sym == S)
|
if(s == S)
|
||||||
return 0;
|
return 0;
|
||||||
p = n->sym->name;
|
p = s->name;
|
||||||
if(p == nil)
|
if(p == nil)
|
||||||
return 0;
|
return 0;
|
||||||
return p[0] == '_' && p[1] == '\0';
|
return p[0] == '_' && p[1] == '\0';
|
||||||
@ -2652,12 +2662,14 @@ genhash(Sym *sym, Type *t)
|
|||||||
// and calling specific hash functions for the others.
|
// and calling specific hash functions for the others.
|
||||||
first = T;
|
first = T;
|
||||||
for(t1=t->type;; t1=t1->down) {
|
for(t1=t->type;; t1=t1->down) {
|
||||||
if(t1 != T && algtype1(t1->type, nil) == AMEM) {
|
if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
|
||||||
if(first == T)
|
if(first == T)
|
||||||
first = t1;
|
first = t1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Run memhash for fields up to this one.
|
// Run memhash for fields up to this one.
|
||||||
|
while(first != T && isblanksym(first->sym))
|
||||||
|
first = first->down;
|
||||||
if(first != T) {
|
if(first != T) {
|
||||||
if(first->down == t1)
|
if(first->down == t1)
|
||||||
size = first->type->width;
|
size = first->type->width;
|
||||||
@ -2867,7 +2879,7 @@ geneq(Sym *sym, Type *t)
|
|||||||
// and calling specific equality tests for the others.
|
// and calling specific equality tests for the others.
|
||||||
first = T;
|
first = T;
|
||||||
for(t1=t->type;; t1=t1->down) {
|
for(t1=t->type;; t1=t1->down) {
|
||||||
if(t1 != T && algtype1(t1->type, nil) == AMEM) {
|
if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
|
||||||
if(first == T)
|
if(first == T)
|
||||||
first = t1;
|
first = t1;
|
||||||
continue;
|
continue;
|
||||||
@ -2875,13 +2887,16 @@ geneq(Sym *sym, Type *t)
|
|||||||
// Run memequal for fields up to this one.
|
// Run memequal for fields up to this one.
|
||||||
// TODO(rsc): All the calls to newname are wrong for
|
// TODO(rsc): All the calls to newname are wrong for
|
||||||
// cross-package unexported fields.
|
// cross-package unexported fields.
|
||||||
|
while(first != T && isblanksym(first->sym))
|
||||||
|
first = first->down;
|
||||||
if(first != T) {
|
if(first != T) {
|
||||||
if(first->down == t1) {
|
if(first->down == t1) {
|
||||||
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
||||||
} else if(first->down->down == t1) {
|
} else if(first->down->down == t1) {
|
||||||
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
||||||
first = first->down;
|
first = first->down;
|
||||||
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
if(!isblanksym(first->sym))
|
||||||
|
fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
|
||||||
} else {
|
} else {
|
||||||
// More than two fields: use memequal.
|
// More than two fields: use memequal.
|
||||||
if(t1 == T)
|
if(t1 == T)
|
||||||
|
19
test/cmp.go
19
test/cmp.go
@ -281,6 +281,25 @@ func main() {
|
|||||||
isfalse(ix != z)
|
isfalse(ix != z)
|
||||||
isfalse(iz != x)
|
isfalse(iz != x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// structs with _ fields
|
||||||
|
{
|
||||||
|
var x = struct {
|
||||||
|
x int
|
||||||
|
_ []int
|
||||||
|
y float64
|
||||||
|
_ float64
|
||||||
|
z int
|
||||||
|
}{
|
||||||
|
x: 1, y: 2, z: 3,
|
||||||
|
}
|
||||||
|
var ix interface{} = x
|
||||||
|
|
||||||
|
istrue(x == x)
|
||||||
|
istrue(x == ix)
|
||||||
|
istrue(ix == x)
|
||||||
|
istrue(ix == ix)
|
||||||
|
}
|
||||||
|
|
||||||
// arrays
|
// arrays
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,10 @@ type T3 struct{ z []int }
|
|||||||
|
|
||||||
var t3 T3
|
var t3 T3
|
||||||
|
|
||||||
|
type T4 struct { _ []int; a float64 }
|
||||||
|
|
||||||
|
var t4 T4
|
||||||
|
|
||||||
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)
|
||||||
@ -46,6 +50,7 @@ func main() {
|
|||||||
|
|
||||||
// Comparison of structs should have a good message
|
// Comparison of structs should have a good message
|
||||||
use(t3 == t3) // ERROR "struct|expected"
|
use(t3 == t3) // ERROR "struct|expected"
|
||||||
|
use(t4 == t4) // ok; the []int is a blank field
|
||||||
|
|
||||||
// Slices, functions, and maps too.
|
// Slices, functions, and maps too.
|
||||||
var x []int
|
var x []int
|
||||||
|
Loading…
Reference in New Issue
Block a user