]> Cypherpunks repositories - gostls13.git/commitdiff
gc: bug250, bug251 - recursive interface types
authorRuss Cox <rsc@golang.org>
Tue, 2 Feb 2010 07:58:49 +0000 (23:58 -0800)
committerRuss Cox <rsc@golang.org>
Tue, 2 Feb 2010 07:58:49 +0000 (23:58 -0800)
Fixes #287.

R=ken2
CC=golang-dev
https://golang.org/cl/199057

src/cmd/gc/dcl.c
src/cmd/gc/walk.c
test/fixedbugs/bug195.go
test/fixedbugs/bug250.go [new file with mode: 0644]
test/fixedbugs/bug251.go [new file with mode: 0644]

index b0b06f7d3223dc860cde34973c369aaa6b9eaad7..9aedf4bcceb3033878b6d693941e8917bc5bf156 100644 (file)
@@ -853,7 +853,10 @@ stotype(NodeList *l, int et, Type **t)
                if(et == TINTER && n->left == N) {
                        // embedded interface - inline the methods
                        if(n->type->etype != TINTER) {
-                               yyerror("interface contains embedded non-interface %T", n->type);
+                               if(n->type->etype == TFORW)
+                                       yyerror("interface type loop involving %T", n->type);
+                               else
+                                       yyerror("interface contains embedded non-interface %T", n->type);
                                continue;
                        }
                        for(t1=n->type->type; t1!=T; t1=t1->down) {
index ffdd17a95da55ed1fe446dfa9373b6813b5560f0..31d1e3091e13072b3c1fe9aeb01e0d5e7946421c 100644 (file)
@@ -122,10 +122,61 @@ walkdeflist(NodeList *l)
                walkdef(l->n);
 }
 
+static NodeList *deftypequeue;
+static int intypedef;
+
+static void
+walkdeftype(Node *n)
+{
+       int maplineno, embedlineno, lno;
+       Type *t;
+
+       lno = lineno;
+       setlineno(n);
+       n->type->sym = n->sym;
+       n->typecheck = 1;
+       typecheck(&n->ntype, Etype);
+       if((t = n->ntype->type) == T) {
+               n->diag = 1;
+               goto ret;
+       }
+
+       // copy new type and clear fields
+       // that don't come along
+       maplineno = n->type->maplineno;
+       embedlineno = n->type->embedlineno;
+       *n->type = *t;
+       t = n->type;
+       t->sym = n->sym;
+       t->local = n->local;
+       t->vargen = n->vargen;
+       t->siggen = 0;
+       t->printed = 0;
+       t->method = nil;
+       t->nod = N;
+       t->printed = 0;
+       t->deferwidth = 0;
+
+       // double-check use of type as map key
+       // TODO(rsc): also use of type as receiver?
+       if(maplineno) {
+               lineno = maplineno;
+               maptype(n->type, types[TBOOL]);
+       }
+       if(embedlineno) {
+               lineno = embedlineno;
+               if(isptr[t->etype])
+                       yyerror("embedded type cannot be a pointer");
+       }
+
+ret:
+       lineno = lno;
+}
+
 void
 walkdef(Node *n)
 {
-       int lno, maplineno, embedlineno;
+       int lno;
        NodeList *init;
        Node *e;
        Type *t;
@@ -214,40 +265,21 @@ walkdef(Node *n)
                n->walkdef = 1;
                n->type = typ(TFORW);
                n->type->sym = n->sym;
-               n->typecheck = 1;
-               typecheck(&n->ntype, Etype);
-               if((t = n->ntype->type) == T) {
-                       n->diag = 1;
-                       goto ret;
-               }
-
-               // copy new type and clear fields
-               // that don't come along
-               maplineno = n->type->maplineno;
-               embedlineno = n->type->embedlineno;
-               *n->type = *t;
-               t = n->type;
-               t->sym = n->sym;
-               t->local = n->local;
-               t->vargen = n->vargen;
-               t->siggen = 0;
-               t->printed = 0;
-               t->method = nil;
-               t->nod = N;
-               t->printed = 0;
-               t->deferwidth = 0;
-
-               // double-check use of type as map key
-               // TODO(rsc): also use of type as receiver?
-               if(maplineno) {
-                       lineno = maplineno;
-                       maptype(n->type, types[TBOOL]);
-               }
-               if(embedlineno) {
-                       lineno = embedlineno;
-                       if(isptr[t->etype])
-                               yyerror("embedded type cannot be a pointer");
+               intypedef++;
+               if(intypedef > 1)
+                       deftypequeue = list(deftypequeue, n);
+               else {
+                       walkdeftype(n);
+                       while(deftypequeue != nil) {
+                               NodeList *l;
+                               
+                               l = deftypequeue;
+                               deftypequeue = nil;
+                               for(; l; l=l->next)
+                                       walkdeftype(l->n);
+                       }
                }
+               intypedef--;
                break;
 
        case OPACK:
index 27bbbd354a62430a817b3d4fb497f6c7e6f99139..221a2eb0986a42f172c205225f30f2ad7561802e 100644 (file)
@@ -19,9 +19,9 @@ type I4 interface {
 }
 
 type I5 interface {
-       I6
+       I6      // ERROR "interface"
 }
 
 type I6 interface {
-       I5      // ERROR "interface"
+       I5
 }
diff --git a/test/fixedbugs/bug250.go b/test/fixedbugs/bug250.go
new file mode 100644 (file)
index 0000000..cd28642
--- /dev/null
@@ -0,0 +1,19 @@
+// $G $D/$F.go || echo BUG: bug250
+
+// Copyright 2010 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 I1 interface {
+       m() I2
+}
+
+type I2 interface {
+       I1
+}
+
+var i1 I1 = i2
+var i2 I2
+var i2a I2 = i1
diff --git a/test/fixedbugs/bug251.go b/test/fixedbugs/bug251.go
new file mode 100644 (file)
index 0000000..1dc712f
--- /dev/null
@@ -0,0 +1,21 @@
+// errchk $G $D/$F.go
+
+// Copyright 2010 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 I1 interface {
+       m() I2
+       I2      // ERROR "loop"
+}
+
+type I2 interface {
+       I1
+}
+
+
+var i1 I1 = i2
+var i2 I2
+var i2a I2 = i1