Commit 44898c7b authored by Russ Cox's avatar Russ Cox

gc: bug250, bug251 - recursive interface types

Fixes #287.

R=ken2
CC=golang-dev
https://golang.org/cl/199057
parent a3372bd6
......@@ -853,6 +853,9 @@ stotype(NodeList *l, int et, Type **t)
if(et == TINTER && n->left == N) {
// embedded interface - inline the methods
if(n->type->etype != TINTER) {
if(n->type->etype == TFORW)
yyerror("interface type loop involving %T", n->type);
else
yyerror("interface contains embedded non-interface %T", n->type);
continue;
}
......
......@@ -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;
intypedef++;
if(intypedef > 1)
deftypequeue = list(deftypequeue, n);
else {
walkdeftype(n);
while(deftypequeue != nil) {
NodeList *l;
// 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]);
l = deftypequeue;
deftypequeue = nil;
for(; l; l=l->next)
walkdeftype(l->n);
}
if(embedlineno) {
lineno = embedlineno;
if(isptr[t->etype])
yyerror("embedded type cannot be a pointer");
}
intypedef--;
break;
case OPACK:
......
......@@ -19,9 +19,9 @@ type I4 interface {
}
type I5 interface {
I6
I6 // ERROR "interface"
}
type I6 interface {
I5 // ERROR "interface"
I5
}
// $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
// 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment