1
0
mirror of https://github.com/golang/go synced 2024-11-25 15:57:57 -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,6 +853,9 @@ stotype(NodeList *l, int et, Type **t)
if(et == TINTER && n->left == N) { if(et == TINTER && n->left == N) {
// embedded interface - inline the methods // embedded interface - inline the methods
if(n->type->etype != TINTER) { 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); yyerror("interface contains embedded non-interface %T", n->type);
continue; continue;
} }

View File

@ -122,10 +122,61 @@ walkdeflist(NodeList *l)
walkdef(l->n); 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 void
walkdef(Node *n) walkdef(Node *n)
{ {
int lno, maplineno, embedlineno; int lno;
NodeList *init; NodeList *init;
Node *e; Node *e;
Type *t; Type *t;
@ -214,40 +265,21 @@ walkdef(Node *n)
n->walkdef = 1; n->walkdef = 1;
n->type = typ(TFORW); n->type = typ(TFORW);
n->type->sym = n->sym; n->type->sym = n->sym;
n->typecheck = 1; intypedef++;
typecheck(&n->ntype, Etype); if(intypedef > 1)
if((t = n->ntype->type) == T) { deftypequeue = list(deftypequeue, n);
n->diag = 1; else {
goto ret; walkdeftype(n);
} while(deftypequeue != nil) {
NodeList *l;
// copy new type and clear fields l = deftypequeue;
// that don't come along deftypequeue = nil;
maplineno = n->type->maplineno; for(; l; l=l->next)
embedlineno = n->type->embedlineno; walkdeftype(l->n);
*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--;
break; break;
case OPACK: case OPACK:

View File

@ -19,9 +19,9 @@ type I4 interface {
} }
type I5 interface { type I5 interface {
I6 I6 // ERROR "interface"
} }
type I6 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