1
0
mirror of https://github.com/golang/go synced 2024-11-25 16:37:57 -07:00

if a struct s contains an anonymous interface value

with method m, s.m() is ok and m now shows up
in s's method set for interface runtime.

see http://cl/28419-p2 for new test interface10.go.

R=ken
OCL=28420
CL=28423
This commit is contained in:
Russ Cox 2009-05-07 13:42:47 -07:00
parent 0d33992866
commit 401a95aa83
5 changed files with 50 additions and 9 deletions

View File

@ -1075,15 +1075,36 @@ Node*
fakethis(void) fakethis(void)
{ {
Node *n; Node *n;
Type *t;
n = nod(ODCLFIELD, N, N); n = nod(ODCLFIELD, N, N);
t = dostruct(N, TSTRUCT); n->type = ptrto(typ(TSTRUCT));
t = ptrto(t);
n->type = t;
return n; return n;
} }
/*
* Is this field a method on an interface?
* Those methods have an anonymous
* *struct{} as the receiver.
* (See fakethis above.)
*/
int
isifacemethod(Type *f)
{
Type *rcvr;
Type *t;
rcvr = getthisx(f->type)->type;
if(rcvr->sym != S)
return 0;
t = rcvr->type;
if(!isptr[t->etype])
return 0;
t = t->type;
if(t->sym != S || t->etype != TSTRUCT || t->type != T)
return 0;
return 1;
}
/* /*
* this generates a new name that is * this generates a new name that is
* pushed down on the declaration list. * pushed down on the declaration list.

View File

@ -822,6 +822,7 @@ void addvar(Node*, Type*, int);
void addtyp(Type*, int); void addtyp(Type*, int);
void addconst(Node*, Node*, int); void addconst(Node*, Node*, int);
Node* fakethis(void); Node* fakethis(void);
int isifacemethod(Type*);
Node* newname(Sym*); Node* newname(Sym*);
Node* oldname(Sym*); Node* oldname(Sym*);
Type* newtype(Sym*); Type* newtype(Sym*);

View File

@ -206,7 +206,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
// get receiver type for this particular method. // get receiver type for this particular method.
this = getthisx(f->type)->type->type; this = getthisx(f->type)->type->type;
if(f->embedded != 2 && isptr[this->etype] && !isptr[progt->etype]) { if(f->embedded != 2 && isptr[this->etype] && !isptr[progt->etype] && !isifacemethod(f)) {
// pointer receiver method but value method set. // pointer receiver method but value method set.
// ignore. // ignore.
if(debug['r']) if(debug['r'])
@ -238,7 +238,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
// but we can generate more efficient code // but we can generate more efficient code
// using genembedtramp if all that is necessary // using genembedtramp if all that is necessary
// is a pointer adjustment and a JMP. // is a pointer adjustment and a JMP.
if(f->embedded && isptr[ifacet->etype]) if(f->embedded && isptr[ifacet->etype] && !isifacemethod(f))
genembedtramp(ifacet, a); genembedtramp(ifacet, a);
else else
genwrapper(ifacet, f, a->sym); genwrapper(ifacet, f, a->sym);

View File

@ -2568,6 +2568,22 @@ expand0(Type *t, int followptr)
u = u->type; u = u->type;
} }
if(u->etype == TINTER) {
for(f=u->type; f!=T; f=f->down) {
if(!exportname(f->sym->name) && strcmp(f->sym->opackage, package) != 0)
continue;
if(f->sym->uniq)
continue;
f->sym->uniq = 1;
sl = mal(sizeof(*sl));
sl->field = f;
sl->link = slist;
sl->followptr = followptr;
slist = sl;
}
return;
}
u = methtype(t); u = methtype(t);
if(u != T) { if(u != T) {
for(f=u->method; f!=T; f=f->down) { for(f=u->method; f!=T; f=f->down) {
@ -2858,7 +2874,7 @@ ifaceokT2I(Type *t0, Type *iface, Type **m)
// if pointer receiver in method, // if pointer receiver in method,
// the method does not exist for value types. // the method does not exist for value types.
rcvr = getthisx(tm->type)->type->type; rcvr = getthisx(tm->type)->type->type;
if(isptr[rcvr->etype] && !isptr[t0->etype] && !followptr) { if(isptr[rcvr->etype] && !isptr[t0->etype] && !followptr && !isifacemethod(tm)) {
if(debug['r']) if(debug['r'])
yyerror("interface pointer mismatch"); yyerror("interface pointer mismatch");
*m = im; *m = im;

View File

@ -192,6 +192,7 @@ implicitstar(Node **nn)
case TMAP: case TMAP:
case TSTRING: case TSTRING:
case TARRAY: case TARRAY:
case TINTER:
break; break;
default: default:
return; return;
@ -1611,8 +1612,10 @@ lookdot(Node *n, Type *t)
n->right = f1->nname; // substitute real name n->right = f1->nname; // substitute real name
n->xoffset = f1->width; n->xoffset = f1->width;
n->type = f1->type; n->type = f1->type;
if(t->etype == TINTER) if(t->etype == TINTER) {
implicitstar(&n->left);
n->op = ODOTINTER; n->op = ODOTINTER;
}
return 1; return 1;
} }
@ -1742,7 +1745,7 @@ loop:
if(l != N || r != T) if(l != N || r != T)
yyerror("assignment count mismatch: %d = %d", yyerror("assignment count mismatch: %d = %d",
listcount(*nl), structcount(*nr)); listcount(*nl), structcount(*nr));
return rev(nn); return rev(nn);
} }