]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/gc: fix computation of equality class of types.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 2 Jul 2013 07:08:43 +0000 (09:08 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 2 Jul 2013 07:08:43 +0000 (09:08 +0200)
A struct with a single field was considered as equivalent to the
field type, which is incorrect is the field is blank.

Fields with padding could make the compiler think some
types are comparable when they are not.

Fixes #5698.

R=rsc, golang-dev, daniel.morsing, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/10271046

src/cmd/gc/subr.c
test/blank.go
test/blank1.go
test/cmp.go
test/cmp6.go
test/fixedbugs/issue5698.go [new file with mode: 0644]

index e49709dc6dbfabb6416ee78614020dcbccf15a90..dee5b016109a6e4229bc518fa9ab18fcf829f478 100644 (file)
@@ -615,23 +615,23 @@ algtype1(Type *t, Type **bad)
                return -1;  // needs special compare
 
        case TSTRUCT:
-               if(t->type != T && t->type->down == T) {
+               if(t->type != T && t->type->down == T && !isblanksym(t->type->sym)) {
                        // One-field struct is same as that one field alone.
                        return algtype1(t->type->type, bad);
                }
                ret = AMEM;
                for(t1=t->type; t1!=T; t1=t1->down) {
-                       // Blank fields and padding must be ignored,
-                       // so need special compare.
-                       if(isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
+                       // All fields must be comparable.
+                       a = algtype1(t1->type, bad);
+                       if(a == ANOEQ)
+                               return ANOEQ;
+
+                       // Blank fields, padded fields, fields with non-memory
+                       // equality need special compare.
+                       if(a != AMEM || isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
                                ret = -1;
                                continue;
                        }
-                       a = algtype1(t1->type, bad);
-                       if(a == ANOEQ)
-                               return ANOEQ;  // not comparable
-                       if(a != AMEM)
-                               ret = -1;  // needs special compare
                }
                return ret;
        }
index 7f7d9f6f7fbac6a7c6ad3eec1eb5df661229d82c..46b61559d780e6da5275e40f4c85282f559b6123 100644 (file)
@@ -27,6 +27,10 @@ func (T) _() {
 func (T) _() {
 }
 
+type U struct {
+       _ struct{ a, b, c int }
+}
+
 const (
        c0 = iota
        _
@@ -116,6 +120,13 @@ func main() {
                if t1 != t2 {
                        panic("T{} != T{}")
                }
+
+               var u1, u2 interface{}
+               u1 = *(*U)(unsafe.Pointer(&T1{1, 2, 3}))
+               u2 = *(*U)(unsafe.Pointer(&T1{4, 5, 6}))
+               if u1 != u2 {
+                       panic("U{} != U{}")
+               }
        }
 
        h(a, b)
index 4edb2db702de0c77cb726f4c166d5c875fd91902..f46a50051b2db087b89b41868ef7df5a64ebe80f 100644 (file)
@@ -13,9 +13,16 @@ var t struct {
        _ int
 }
 
+type T struct {
+      _ []int
+}
+
 func main() {
        _()     // ERROR "cannot use _ as value"
        x := _+1        // ERROR "cannot use _ as value"
        _ = x
        _ = t._ // ERROR "cannot refer to blank field"
+
+      var v1, v2 T
+      _ = v1 == v2 // ERROR "cannot be compared|non-comparable"
 }
index 5be64561d597c5d2fcf012d1e57ae7b5134de953..7183f02079558d70b8ef56ca938b5a0ef8f4d4e8 100644 (file)
@@ -296,7 +296,7 @@ func main() {
        {
                var x = struct {
                        x int
-                       _ []int
+                       _ string
                        y float64
                        _ float64
                        z int
index 7d99aae18b322ac4ca889e8d91492b3aefc08436..839c274bccae225a424aa5eac66873efaa25988f 100644 (file)
@@ -53,7 +53,7 @@ func main() {
 
        // Comparison of structs should have a good message
        use(t3 == t3) // ERROR "struct|expected"
-       use(t4 == t4) // ok; the []int is a blank field
+       use(t4 == t4) // ERROR "cannot be compared|non-comparable"
 
        // Slices, functions, and maps too.
        var x []int
diff --git a/test/fixedbugs/issue5698.go b/test/fixedbugs/issue5698.go
new file mode 100644 (file)
index 0000000..035bbd3
--- /dev/null
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5698: can define a key type with slices.
+
+package main
+
+type Key struct {
+       a int16 // the compiler was confused by the padding.
+       b []int
+}
+
+type Val struct{}
+
+type Map map[Key]Val // ERROR "invalid map key type"