1
0
mirror of https://github.com/golang/go synced 2024-11-22 05:44:41 -07:00

gc: recursive interface embedding

Fixes #287.

R=ken2
CC=golang-dev
https://golang.org/cl/215048
This commit is contained in:
Russ Cox 2010-02-18 11:15:36 -08:00
parent cf015fd0b8
commit 1734cb02e7
7 changed files with 76 additions and 40 deletions

View File

@ -809,6 +809,15 @@ stotype(NodeList *l, int et, Type **t)
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("stotype: oops %N\n", n); fatal("stotype: oops %N\n", n);
if(n->right != N) { if(n->right != N) {
if(et == TINTER && n->left != N) {
// queue resolution of method type for later.
// right now all we need is the name list.
// avoids cycles for recursive interface types.
n->type = typ(TINTERMETH);
n->type->nod = n->right;
n->right = N;
queuemethod(n);
} else {
typecheck(&n->right, Etype); typecheck(&n->right, Etype);
n->type = n->right->type; n->type = n->right->type;
if(n->type == T) { if(n->type == T) {
@ -828,6 +837,7 @@ stotype(NodeList *l, int et, Type **t)
t1->embedlineno = lineno; t1->embedlineno = lineno;
} }
} }
}
if(n->type == T) { if(n->type == T) {
// assume error already printed // assume error already printed

View File

@ -462,6 +462,7 @@ enum
// pseudo-type for frame layout // pseudo-type for frame layout
TFUNCARGS, TFUNCARGS,
TCHANARGS, TCHANARGS,
TINTERMETH,
NTYPE, NTYPE,
}; };
@ -1088,6 +1089,7 @@ Node* typecheckconv(Node*, Node*, Type*, int, char*);
int checkconv(Type*, Type*, int, int*, int*, char*); int checkconv(Type*, Type*, int, int*, int*, char*);
Node* typecheck(Node**, int); Node* typecheck(Node**, int);
int islvalue(Node*); int islvalue(Node*);
void queuemethod(Node*);
/* /*
* const.c * const.c

View File

@ -51,7 +51,7 @@ typecheck(Node **np, int top)
int et, op; int et, op;
Node *n, *l, *r; Node *n, *l, *r;
NodeList *args; NodeList *args;
int lno, ok, ntop, ct; int lno, ok, ntop;
Type *t; Type *t;
Sym *sym; Sym *sym;
Val v; Val v;

View File

@ -115,11 +115,25 @@ gettype(Node **np, NodeList **init)
dump("after gettype", *np); dump("after gettype", *np);
} }
void static int nwalkdeftype;
walkdeflist(NodeList *l) static NodeList *methodqueue;
static void
domethod(Node *n)
{ {
for(; l; l=l->next) Node *nt;
walkdef(l->n);
nt = n->type->nod;
typecheck(&nt, Etype);
if(nt->type == T) {
// type check failed; leave empty func
n->type->etype = TFUNC;
n->type->nod = N;
return;
}
*n->type = *nt->type;
n->type->nod = N;
checkwidth(n->type);
} }
static void static void
@ -127,7 +141,9 @@ walkdeftype(Node *n)
{ {
int maplineno, embedlineno, lno; int maplineno, embedlineno, lno;
Type *t; Type *t;
NodeList *l;
nwalkdeftype++;
lno = lineno; lno = lineno;
setlineno(n); setlineno(n);
n->type->sym = n->sym; n->type->sym = n->sym;
@ -168,6 +184,28 @@ walkdeftype(Node *n)
ret: ret:
lineno = lno; lineno = lno;
// if there are no type definitions going on, it's safe to
// try to resolve the method types for the interfaces
// we just read.
if(nwalkdeftype == 1) {
while((l = methodqueue) != nil) {
methodqueue = nil;
for(; l; l=l->next)
domethod(l->n);
}
}
nwalkdeftype--;
}
void
queuemethod(Node *n)
{
if(nwalkdeftype == 0) {
domethod(n);
return;
}
methodqueue = list(methodqueue, n);
} }
void void

View File

@ -8,14 +8,14 @@ package main
type I1 interface { type I1 interface {
m() I2 m() I2
I2 // ERROR "loop|interface" I2
} }
type I2 interface { type I2 interface {
I1 I1 // ERROR "loop|interface"
} }
var i1 I1 = i2 var i1 I1 = i2 // ERROR "need type assertion"
var i2 I2 var i2 I2
var i2a I2 = i1 var i2a I2 = i1

View File

@ -150,17 +150,3 @@ throw: interface conversion
panic PC=xxx panic PC=xxx
== bugs/ == bugs/
=========== bugs/bug250.go
bugs/bug250.go:14: interface type loop involving I1
bugs/bug250.go:17: need type assertion to use I2 as I1
missing m() I2
BUG: bug250
=========== bugs/bug251.go
BUG: errchk: bugs/bug251.go:11: missing expected error: 'loop|interface'
errchk: bugs/bug251.go: unmatched error messages:
==================================================
bugs/bug251.go:15: interface type loop involving I1
bugs/bug251.go:19: need type assertion to use I2 as I1
==================================================