]> Cypherpunks repositories - gostls13.git/commitdiff
implement new restrictions on what
authorRuss Cox <rsc@golang.org>
Mon, 26 Jan 2009 17:56:42 +0000 (09:56 -0800)
committerRuss Cox <rsc@golang.org>
Mon, 26 Jan 2009 17:56:42 +0000 (09:56 -0800)
can be compared/hashed.

R=r
DELTA=351  (201 added, 80 deleted, 70 changed)
OCL=23423
CL=23481

15 files changed:
src/cmd/gc/go.h
src/cmd/gc/subr.c
src/runtime/chan.c
src/runtime/hashmap.c
src/runtime/iface.c
src/runtime/runtime.c
src/runtime/runtime.h
test/bigalg.go
test/cmp1.go [new file with mode: 0644]
test/cmp2.go [new file with mode: 0644]
test/cmp3.go [new file with mode: 0644]
test/cmp4.go [new file with mode: 0644]
test/cmp5.go [new file with mode: 0644]
test/golden.out
test/map.go

index b04790d662954ed3c8d18d9e18e4d43e2578719a..6dc8393bd71f505603bf13402e532ea43c0dae2e 100644 (file)
@@ -37,13 +37,12 @@ enum
        PRIME10         = 10093,
 
        AUNK            = 100,
+
        // these values are known by runtime
-       ASIMP           = 0,
+       AMEM            = 0,
+       ANOEQ,
        ASTRING,
-       APTR,
        AINTER,
-       ASLICE,
-       ASTRUCT,
 
        BADWIDTH        = -1000000000
 };
index 0650a634e30dfd10815a1acec8a0b0ecf2c4609f..bfcdd08f5b832c0f49238e0c0ff80dc67afa28dd 100644 (file)
@@ -291,26 +291,16 @@ algtype(Type *t)
 {
        int a;
 
-       a = AUNK;
-       if(issimple[t->etype])
-               a = ASIMP;      // simple mem
+       if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN)
+               a = AMEM;       // just bytes (int, ptr, etc)
        else
        if(t->etype == TSTRING)
                a = ASTRING;    // string
        else
-       if(isptr[simtype[t->etype]])
-               a = APTR;       // pointer
-       else
-       if(isslice(t))
-               a = ASLICE;
-       else
-       if(t->etype == TSTRUCT)
-               a = ASTRUCT;
-       else
-       if(isinter(t))
+       if(t->etype == TINTER)
                a = AINTER;     // interface
-//     else
-//             fatal("algtype: cant find type %T", t);
+       else
+               a = ANOEQ;      // just bytes, but no hash/eq
        return a;
 }
 
index 929d07f7ea3f071e3bc4fced3997415f18916b5e..6f89fa395357ae07abd7f559834780d7d6e7a3ab 100644 (file)
@@ -88,17 +88,9 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint,
        Hchan *c;
        int32 i;
 
-       switch(elemalg){
-       case ASIMP:
-       case ASTRING:
-       case APTR:
-       case AINTER:
-       case AARRAY:
-       case ASTRUCT:
-               break;
-       default:
+       if(elemalg >= nelem(algarray)) {
                printf("chan(alg=%d)\n", elemalg);
-               throw("sys·newchan: unsupported channel element type");
+               throw("sys·newchan: unsupported elem type");
        }
 
        c = mal(sizeof(*c));
index 5be990c49c0203fe72d2befc232ca383e8e78730..f54d13197c9ee930f7f8008b8e3f1636b31ce841 100644 (file)
@@ -663,28 +663,12 @@ sys·newmap(uint32 keysize, uint32 valsize,
 {
        Hmap *h;
 
-       switch(keyalg) {
-       case ASIMP:
-       case ASTRING:
-       case APTR:
-       case AINTER:
-       case AARRAY:
-       case ASTRUCT:
-               break;
-       default:
+       if(keyalg >= nelem(algarray) || algarray[keyalg].hash == nohash) {
                printf("map(keyalg=%d)\n", keyalg);
                throw("sys·newmap: unsupported map key type");
        }
 
-       switch(valalg) {
-       case ASIMP:
-       case ASTRING:
-       case APTR:
-       case AINTER:
-       case AARRAY:
-       case ASTRUCT:
-               break;
-       default:
+       if(valalg >= nelem(algarray)) {
                printf("map(valalg=%d)\n", valalg);
                throw("sys·newmap: unsupported map value type");
        }
index 70e2b4f04c042f6dbf3b7a431837efe88fad2aac..99116806a3918db4a963db293a67fffeaad3359c 100644 (file)
@@ -404,11 +404,32 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
        FLUSH(&ok);
 }
 
-// ifaceeq(i1 any, i2 any) (ret bool);
-void
-sys·ifaceeq(Iface i1, Iface i2, bool ret)
+uint64
+ifacehash(Iface a)
+{
+       int32 alg, wid;
+       
+       if(a.type == nil)
+               return 0;
+       alg = a.type->sigt->hash;
+       wid = a.type->sigt->offset;
+       if(algarray[alg].hash == nohash) {
+               // calling nohash will throw too,
+               // but we can print a better error.
+               printf("hash of unhashable type %s\n", a.type->sigt->name);
+               throw("interface hash");
+       }
+       if(wid <= sizeof a.data)
+               return algarray[alg].hash(wid, &a.data);
+       else
+               return algarray[alg].hash(wid, a.data);
+}
+
+bool
+ifaceeq(Iface i1, Iface i2)
 {
        int32 alg, wid;
+       bool ret;
 
        if(iface_debug) {
                prints("Ieq i1=");
@@ -438,6 +459,13 @@ sys·ifaceeq(Iface i1, Iface i2, bool ret)
        if(wid != i2.type->sigt->offset)
                goto no;
 
+       if(algarray[alg].equal == noequal) {
+               // calling noequal will throw too,
+               // but we can print a better error.
+               printf("comparing uncomparable type %s\n", i1.type->sigt->name);
+               throw("interface compare");
+       }
+
        if(wid <= sizeof i1.data) {
                if(!algarray[alg].equal(wid, &i1.data, &i2.data))
                        goto no;
@@ -454,6 +482,14 @@ no:
                sys·printbool(ret);
                prints("\n");
        }
+       return ret;
+}
+
+// ifaceeq(i1 any, i2 any) (ret bool);
+void
+sys·ifaceeq(Iface i1, Iface i2, bool ret)
+{
+       ret = ifaceeq(i1, i2);
        FLUSH(&ret);
 }
 
@@ -526,7 +562,7 @@ fakesigt(string type, bool indir)
        sigt = mal(2*sizeof sigt[0]);
        sigt[0].name = mal(type->len + 1);
        mcpy(sigt[0].name, type->str, type->len);
-       sigt[0].hash = ASIMP;   // alg
+       sigt[0].hash = AMEM;    // alg
        if(indir)
                sigt[0].offset = 2*sizeof(niliface.data);  // big width
        else
index 29a67b190d16b8e14b3ca1757392c081fbde0f9a..ce9349383c5d36e1af3eeffd365c33865a2256b0 100644 (file)
@@ -328,57 +328,52 @@ strprint(uint32 s, string *a)
        sys·printstring(*a);
 }
 
-static void
-strcopy(uint32 s, string *a, string *b)
+static uint64
+interhash(uint32 s, Iface *a)
 {
        USED(s);
-       if(b == nil) {
-               *a = nil;
-               return;
-       }
-       *a = *b;
+       return ifacehash(*a);
 }
 
-static uint64
-ptrhash(uint32 s, void **a)
+static void
+interprint(uint32 s, Iface *a)
 {
-       return memhash(s, *a);
+       USED(s);
+       sys·printinter(*a);
 }
 
 static uint32
-ptrequal(uint32 s, void **a, void **b)
+interequal(uint32 s, Iface *a, Iface *b)
 {
-       USED(s, a, b);
-       prints("ptrequal\n");
-       return 0;
+       USED(s);
+       return ifaceeq(*a, *b);
 }
 
-static void
-ptrprint(uint32 s, void **a)
+uint64
+nohash(uint32 s, void *a)
 {
-       USED(s, a);
-       prints("ptrprint\n");
+       USED(s);
+       USED(a);
+       throw("hash of unhashable type");
+       return 0;
 }
 
-static void
-ptrcopy(uint32 s, void **a, void **b)
+uint32
+noequal(uint32 s, void *a, void *b)
 {
        USED(s);
-       if(b == nil) {
-               *a = nil;
-               return;
-       }
-       *a = *b;
+       USED(a);
+       USED(b);
+       throw("comparing uncomparable types");
+       return 0;
 }
 
 Alg
 algarray[] =
 {
-[ASIMP]                { memhash, memequal, memprint, memcopy },
-[ASTRING]      { strhash, strequal, strprint, strcopy },
-[APTR]         { memhash, memequal, memprint, memcopy },       // TODO: ptr routines
-[AINTER]       { memhash, memequal, memprint, memcopy },       // TODO: interface routines
-[ASTRUCT]      { memhash, memequal, memprint, memcopy },       // TODO: what goes here?
-[AARRAY]       { memhash, memequal, memprint, memcopy },       // TODO: what goes here?
+[AMEM] { memhash, memequal, memprint, memcopy },
+[ANOEQ]        { nohash, noequal, memprint, memcopy },
+[ASTRING]      { strhash, strequal, strprint, memcopy },
+[AINTER]               { interhash, interequal, interprint, memcopy },
 };
 
index bc6b2f76d5be31b43011994a86d5c16dca430787..47103e253addbcf1c2b18d701a0a4ded396dd0c1 100644 (file)
@@ -226,18 +226,17 @@ struct    Func
  */
 enum
 {
-       ASIMP           = 0,
+       AMEM,
+       ANOEQ,
        ASTRING,
-       APTR,
        AINTER,
-       AARRAY,
-       ASTRUCT,
+       Amax
 };
 
 /*
  * external data
  */
-extern Alg     algarray[];
+extern Alg     algarray[Amax];
 extern string  emptystring;
 G*     allg;
 int32  goidgen;
@@ -299,6 +298,10 @@ void*      stackalloc(uint32);
 void   stackfree(void*);
 MCache*        allocmcache(void);
 void   mallocinit(void);
+bool   ifaceeq(Iface, Iface);
+uint64 ifacehash(Iface);
+uint64 nohash(uint32, void*);
+uint32 noequal(uint32, void*, void*);
 
 #pragma        varargck        argpos  printf  1
 
@@ -366,6 +369,7 @@ void        notewakeup(Note*);
 #define sys_printfloat sys·printfloat
 #define sys_printhex sys·printhex
 #define sys_printint sys·printint
+#define sys_printinter sys·printinter
 #define sys_printpc sys·printpc
 #define sys_printpointer sys·printpointer
 #define sys_printstring sys·printstring
@@ -393,6 +397,7 @@ void*       sys_getcallerpc(void*);
 void   sys_printbool(bool);
 void   sys_printfloat(float64);
 void   sys_printint(int64);
+void   sys_printinter(Iface);
 void   sys_printstring(string);
 void   sys_printpc(void*);
 void   sys_printpointer(void*);
index 434eecf5d26fde11411d17fb896e59ed41caa503..afeccdf8f0f2805c6177da9655073bf3bc5b2bd0 100644 (file)
@@ -62,25 +62,6 @@ func maptest() {
        }
 }
 
-var mt1 = make(map[T]int)
-var ma1 = make(map[[]int] int)
-
-func maptest2() {
-       mt1[t] = 123;
-       t1 := t;
-       val, ok := mt1[t1];
-       if val != 123 || !ok {
-               println("fail: map key struct", val, ok);
-       }
-
-       ma1[a] = 345;
-       a1 := a;
-       val, ok = ma1[a1];
-       if val != 345 || !ok {
-               panic("map key array", val, ok);
-       }
-}
-
 var ct = make(chan T)
 var ca = make(chan []int)
 
@@ -136,7 +117,6 @@ func interfacetest() {
 func main() {
        arraycmptest();
        maptest();
-       maptest2();
        chantest();
        interfacetest();
 }
diff --git a/test/cmp1.go b/test/cmp1.go
new file mode 100644 (file)
index 0000000..82e932f
--- /dev/null
@@ -0,0 +1,66 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+import "unsafe"
+
+func use(bool) { }
+
+func stringptr(s string) uintptr {
+       return *(&s).(unsafe.Pointer).(*uintptr);
+}
+
+func isfalse(b bool) {
+       if b { panicln("wanted false, got true") } // stack will explain where
+}
+
+func istrue(b bool) {
+       if !b { panicln("wanted true, got false") } // stack will explain where
+}
+
+func main()
+{
+       var a []int;
+       var b map[string]int;
+
+       var c string = "hello";
+       var d string = "hel";   // try to get different pointer
+       d = d + "lo";
+       if stringptr(c) == stringptr(d) {
+               panic("compiler too smart -- got same string")
+       }
+
+       var e = make(chan int);
+
+       var ia interface{} = a;
+       var ib interface{} = b;
+       var ic interface{} = c;
+       var id interface{} = d;
+       var ie interface{} = e;
+
+       // these comparisons are okay because
+       // string compare is okay and the others
+       // are comparisons where the types differ.
+       isfalse(ia == ib);
+       isfalse(ia == ic);
+       isfalse(ia == id);
+       isfalse(ib == ic);
+       isfalse(ib == id);
+       istrue(ic == id);
+       istrue(ie == ie);
+
+       // map of interface should use == on interface values,
+       // not memory.
+       // TODO: should m[c], m[d] be valid here?
+       var m = make(map[interface{}] int);
+       m[ic] = 1;
+       m[id] = 2;
+       if m[ic] != 2 {
+               panic("m[ic] = ", m[ic]);
+       }
+}
+
diff --git a/test/cmp2.go b/test/cmp2.go
new file mode 100644 (file)
index 0000000..d43cfcd
--- /dev/null
@@ -0,0 +1,16 @@
+// $G $D/$F.go && $L $F.$A && ! ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+func use(bool) { }
+
+func main()
+{
+       var a []int;
+       var ia interface{} = a;
+       use(ia == ia);
+}
diff --git a/test/cmp3.go b/test/cmp3.go
new file mode 100644 (file)
index 0000000..06a67bd
--- /dev/null
@@ -0,0 +1,16 @@
+// $G $D/$F.go && $L $F.$A && ! ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+func use(bool) { }
+
+func main()
+{
+       var b map[string]int;
+       var ib interface{} = b;
+       use(ib == ib);
+}
diff --git a/test/cmp4.go b/test/cmp4.go
new file mode 100644 (file)
index 0000000..61787b0
--- /dev/null
@@ -0,0 +1,15 @@
+// $G $D/$F.go && $L $F.$A && ! ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+func main()
+{
+       var a []int;
+       var ia interface{} = a;
+       var m = make(map[interface{}] int);
+       m[ia] = 1;
+}
diff --git a/test/cmp5.go b/test/cmp5.go
new file mode 100644 (file)
index 0000000..7500974
--- /dev/null
@@ -0,0 +1,15 @@
+// $G $D/$F.go && $L $F.$A && ! ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+func main()
+{
+       var b map[string]int;
+       var ib interface{} = b;
+       var m = make(map[interface{}] int);
+       m[ib] = 1;
+}
index 023b96edd04c99807461bede9fbfdf0c4a92b571..163242bc230e0779e8d48b4a394dc74ea4b1e4f6 100644 (file)
@@ -1,4 +1,36 @@
 
+=========== ./cmp2.go
+comparing uncomparable type []int
+throw: interface compare
+SIGSEGV: segmentation violation
+Faulting address: 0x0
+pc: xxx
+
+
+=========== ./cmp3.go
+comparing uncomparable type map[string] int
+throw: interface compare
+SIGSEGV: segmentation violation
+Faulting address: 0x0
+pc: xxx
+
+
+=========== ./cmp4.go
+hash of unhashable type []int
+throw: interface hash
+SIGSEGV: segmentation violation
+Faulting address: 0x0
+pc: xxx
+
+
+=========== ./cmp5.go
+hash of unhashable type map[string] int
+throw: interface hash
+SIGSEGV: segmentation violation
+Faulting address: 0x0
+pc: xxx
+
+
 =========== ./convlit.go
 BUG: errchk: ./convlit.go: missing expected error message on line 16: 'conver|incompatible'
 errchk: ./convlit.go: missing expected error message on line 22: 'convert'
index 51c6fe5f5b4d9dd3e76bdeb9346dffb4f1a14202..085502bf521244fcdd85d5d787edfdb5043e0121 100644 (file)
@@ -52,7 +52,7 @@ func main() {
        mipT := make(map[int] *T);
        mpTi := make(map[*T] int);
        mit := make(map[int] T);
-       mti := make(map[T] int);
+//     mti := make(map[T] int);
 
        type M map[int] int;
        mipM := make(map[int] M);
@@ -88,7 +88,7 @@ func main() {
                mpTi[apT[i]] = i;
                mipM[i] = m;
                mit[i] = t;
-               mti[t] = i;
+       //      mti[t] = i;
        }
 
        // test len
@@ -122,15 +122,15 @@ func main() {
        if len(mpTi) != count {
                fmt.Printf("len(mpTi) = %d\n", len(mpTi));
        }
-       if len(mti) != count {
-               fmt.Printf("len(mti) = %d\n", len(mti));
-       }
+//     if len(mti) != count {
+//             fmt.Printf("len(mti) = %d\n", len(mti));
+//     }
        if len(mipM) != count {
                fmt.Printf("len(mipM) = %d\n", len(mipM));
        }
-       if len(mti) != count {
-               fmt.Printf("len(mti) = %d\n", len(mti));
-       }
+//     if len(mti) != count {
+//             fmt.Printf("len(mti) = %d\n", len(mti));
+//     }
        if len(mit) != count {
                fmt.Printf("len(mit) = %d\n", len(mit));
        }
@@ -174,15 +174,15 @@ func main() {
                if(mpTi[apT[i]] != i) {
                        fmt.Printf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]]);
                }
-               if(mti[t] != i) {
-                       fmt.Printf("mti[%s] = %s\n", s, mti[t]);
-               }
+       //      if(mti[t] != i) {
+       //              fmt.Printf("mti[%s] = %s\n", s, mti[t]);
+       //      }
                if (mipM[i][i] != i + 1) {
                        fmt.Printf("mipM[%d][%d] = %d\n", i, i, mipM[i][i]);
                }
-               if(mti[t] != i) {
-                       fmt.Printf("mti[%v] = %d\n", t, mti[t]);
-               }
+       //      if(mti[t] != i) {
+       //              fmt.Printf("mti[%v] = %d\n", t, mti[t]);
+       //      }
                if(mit[i].i != int64(i) || mit[i].f != f) {
                        fmt.Printf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f);
                }
@@ -314,16 +314,16 @@ func main() {
                                fmt.Printf("tuple existence assign: mit[%d]\n", i);
                        }
                }
-               {
-                       a, b := mti[t];
-                       if !b {
-                               fmt.Printf("tuple existence decl: mti[%d]\n", i);
-                       }
-                       a, b = mti[t];
-                       if !b {
-                               fmt.Printf("tuple existence assign: mti[%d]\n", i);
-                       }
-               }
+//             {
+//                     a, b := mti[t];
+//                     if !b {
+//                             fmt.Printf("tuple existence decl: mti[%d]\n", i);
+//                     }
+//                     a, b = mti[t];
+//                     if !b {
+//                             fmt.Printf("tuple existence assign: mti[%d]\n", i);
+//                     }
+//             }
        }
 
        // test nonexistence with tuple check
@@ -442,16 +442,16 @@ func main() {
                                fmt.Printf("tuple nonexistence assign: mipM[%d]", i);
                        }
                }
-               {
-                       a, b := mti[t];
-                       if b {
-                               fmt.Printf("tuple nonexistence decl: mti[%d]", i);
-                       }
-                       a, b = mti[t];
-                       if b {
-                               fmt.Printf("tuple nonexistence assign: mti[%d]", i);
-                       }
-               }
+//             {
+//                     a, b := mti[t];
+//                     if b {
+//                             fmt.Printf("tuple nonexistence decl: mti[%d]", i);
+//                     }
+//                     a, b = mti[t];
+//                     if b {
+//                             fmt.Printf("tuple nonexistence assign: mti[%d]", i);
+//                     }
+//             }
                {
                        a, b := mit[i];
                        if b {