]> Cypherpunks repositories - gostls13.git/commitdiff
more interface checks:
authorRuss Cox <rsc@golang.org>
Wed, 8 Oct 2008 16:21:57 +0000 (09:21 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 8 Oct 2008 16:21:57 +0000 (09:21 -0700)
- pointer to interface cannot have methods
- record type names for better runtime error

R=r,ken
DELTA=85  (80 added, 0 deleted, 5 changed)
OCL=16658
CL=16722

src/cmd/6g/obj.c
src/cmd/gc/subr.c
src/runtime/iface.c
test/golden.out
test/interface1.go [new file with mode: 0644]
test/interface2.go [new file with mode: 0644]

index 28eb6b1c514eab4695be1c2a3e36453b35e8e09c..b4f44bbc3f8307b59d1e50d8e1540b9250a8c993 100644 (file)
@@ -466,6 +466,7 @@ dumpsignatures(void)
        Addr at, ao, ac, ad;
        Prog *p;
        char *sp;
+       char buf[NSYMB];
 
        // copy externdcl list to signatlist
        for(d=externdcl; d!=D; d=d->forw) {
@@ -583,7 +584,7 @@ dumpsignatures(void)
                        sp = strchr(s1->name, '_');
                        if(sp != nil)
                                a->name = sp+1;
-                       
+
                        a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
                        a->perm = o;
                        snprint(namebuf, sizeof(namebuf), "%s_%s",
@@ -608,7 +609,9 @@ dumpsignatures(void)
                p->to.offset = stringo;
                ot += widthptr;
 
-               datastring("", 1);
+               // save type name for runtime error message
+               snprint(buf, sizeof buf, "%T", t);
+               datastring(buf, strlen(buf)+1);
 
                if(et == TINTER) {
                        // first field of an interface signature
@@ -733,6 +736,7 @@ dumpsignatures(void)
                                ot += widthptr;
                        }
                        datastring(b->name, strlen(b->name)+1);
+
                }
 
                // nil field name at end
index c15039e36f7e6edb53da6cb309d72ff90d4ad4dd..ddce14e6f32cc75fab13b68b7e99103e12cc76eb 100644 (file)
@@ -1406,6 +1406,10 @@ ismethod(Type *t)
        if(t == T)
                return T;
 
+       // no interfaces
+       if(t->etype == TINTER || (t->etype == tptr && t->type->etype == TINTER))
+               return T;
+
        a = algtype(t);
 
        // direct receiver
index e8c4cd69392c7536382d989da68283c9a38434e5..089975b92326aa0bbf2adb41234b6bf9c789c490 100644 (file)
@@ -40,7 +40,7 @@ static        Map*    hash[1009];
 static void
 printsigi(Sigi *si)
 {
-       int32 i, n;
+       int32 i;
        byte *name;
 
        sys·printpointer(si);
@@ -125,7 +125,7 @@ hashmap(Sigi *si, Sigt *st)
        m->sigi = si;
        m->sigt = st;
 
-       nt = 0;
+       nt = 1;
        for(ni=1; (iname=si[ni].name) != nil; ni++) {   // ni=1: skip first word
                // pick up next name from
                // interface signature
@@ -136,9 +136,14 @@ hashmap(Sigi *si, Sigt *st)
                        // from structure signature
                        sname = st[nt].name;
                        if(sname == nil) {
+                               prints("cannot convert type ");
+                               prints((int8*)st[0].name);
+                               prints(" to interface ");
+                               prints((int8*)si[0].name);
+                               prints(": missing method ");
                                prints((int8*)iname);
-                               prints("");
-                               throw("hashmap: failed to find method");
+                               prints("\n");
+                               throw("interface conversion");
                                m->bad = 1;
                                m->link = hash[h];
                                hash[h] = m;
index 9e8cbcf2ed8e2ce78eb2392aa208b75353005798..5fcde598244693b223173134440315a896fcd678 100644 (file)
@@ -2,6 +2,20 @@
 =========== ./helloworld.go
 hello, world
 
+=========== ./interface1.go
+./interface1.go:5: syntax error near package
+./interface1.go:31: illegal types for operand: AS
+       interface { Next () (*Inst) }
+       *Inst
+
+=========== ./interface2.go
+cannot convert type S to interface I: missing method Foo
+throw: interface conversion
+SIGSEGV: segmentation violation
+Faulting address: 0x0
+pc: xxx
+
+
 =========== ./peano.go
 0! = 1
 1! = 1
@@ -64,6 +78,7 @@ BUG: compilation should succeed
 
 =========== bugs/bug074.go
 bugs/bug074.go:6: syntax error near string
+bugs/bug074.go:6: syntax error near string
 bugs/bug074.go:7: x: undefined
 BUG: compiler crashes - Bus error
 
diff --git a/test/interface1.go b/test/interface1.go
new file mode 100644 (file)
index 0000000..a6430cd
--- /dev/null
@@ -0,0 +1,37 @@
+// errchk $G $D/$F.go
+
+// 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
+
+package main
+
+type Inst interface {
+       Next()  *Inst;
+}
+
+type Regexp struct {
+       code *[]Inst;
+       start   Inst;
+}
+
+type Start struct {
+       foo     *Inst;
+}
+
+func (start *Start) Next() *Inst { return nil }
+
+
+func AddInst(Inst) *Inst {
+       print("ok in addinst\n");
+       return nil
+}
+
+func main() {
+       re := new(Regexp);
+       print("call addinst\n");
+       var x Inst = AddInst(new(Start));
+       print("return from  addinst\n");
+}
diff --git a/test/interface2.go b/test/interface2.go
new file mode 100644 (file)
index 0000000..8dfc9d8
--- /dev/null
@@ -0,0 +1,23 @@
+// $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
+
+type S struct
+
+type I interface {
+       Foo()
+}
+
+func main() {
+       var s *S;
+       var i I;
+       i = s;
+}
+
+// hide S down here to avoid static warning
+type S struct {
+}