mirror of
https://github.com/golang/go
synced 2024-11-22 08:14: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:
parent
a3372bd655
commit
44898c7b76
@ -853,7 +853,10 @@ 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) {
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
for(t1=n->type->type; t1!=T; t1=t1->down) {
|
for(t1=n->type->type; t1!=T; t1=t1->down) {
|
||||||
|
@ -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:
|
||||||
|
@ -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
19
test/fixedbugs/bug250.go
Normal 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
21
test/fixedbugs/bug251.go
Normal 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
|
Loading…
Reference in New Issue
Block a user