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:
parent
0d33992866
commit
401a95aa83
@ -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.
|
||||||
|
@ -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*);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user