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:
parent
cf015fd0b8
commit
1734cb02e7
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
@ -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
|
|
||||||
==================================================
|
|
||||||
|
Loading…
Reference in New Issue
Block a user