1
0
mirror of https://github.com/golang/go synced 2024-11-21 20:34:40 -07:00

gc: bug250, bug251 - recursive interface types

Fixes #287.

R=ken2
CC=golang-dev
https://golang.org/cl/199057
This commit is contained in:
Russ Cox 2010-02-01 23:58:49 -08:00
parent a3372bd655
commit 44898c7b76
5 changed files with 112 additions and 37 deletions

View 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) {

View 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:

View File

@ -19,9 +19,9 @@ type I4 interface {
}
type I5 interface {
I6
I6 // ERROR "interface"
}
type I6 interface {
I5 // ERROR "interface"
I5
}

19
test/fixedbugs/bug250.go Normal file
View File

@ -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

21
test/fixedbugs/bug251.go Normal file
View File

@ -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