]> Cypherpunks repositories - gostls13.git/commitdiff
if a struct s contains an anonymous interface value
authorRuss Cox <rsc@golang.org>
Thu, 7 May 2009 20:42:47 +0000 (13:42 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 7 May 2009 20:42:47 +0000 (13:42 -0700)
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

src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/obj.c
src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 202f48f858bca3c2f5fe6f2dc1ac29a1d3f463d7..14617fb6045c373f8f6bb65954b5e835dff64d50 100644 (file)
@@ -1075,15 +1075,36 @@ Node*
 fakethis(void)
 {
        Node *n;
-       Type *t;
 
        n = nod(ODCLFIELD, N, N);
-       t = dostruct(N, TSTRUCT);
-       t = ptrto(t);
-       n->type = t;
+       n->type = ptrto(typ(TSTRUCT));
        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
  * pushed down on the declaration list.
index c8f3cbf3fe9ad2cc9d9cbb07d5f3bbd4d5ed04bb..a7f10ced2902814908cf17b74f9b1f1b90f7ccae 100644 (file)
@@ -822,6 +822,7 @@ void        addvar(Node*, Type*, int);
 void   addtyp(Type*, int);
 void   addconst(Node*, Node*, int);
 Node*  fakethis(void);
+int    isifacemethod(Type*);
 Node*  newname(Sym*);
 Node*  oldname(Sym*);
 Type*  newtype(Sym*);
index e55e5def8c895321835b62527372f2b6d1c8ee9f..ee0fd53dcdd189e0304e5a93fe1f3afaad92e4d3 100644 (file)
@@ -206,7 +206,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
 
                // get receiver type for this particular method.
                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.
                        // ignore.
                        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
                                // using genembedtramp if all that is necessary
                                // is a pointer adjustment and a JMP.
-                               if(f->embedded && isptr[ifacet->etype])
+                               if(f->embedded && isptr[ifacet->etype] && !isifacemethod(f))
                                        genembedtramp(ifacet, a);
                                else
                                        genwrapper(ifacet, f, a->sym);
index 65bf8543f221eb2c3ffa5594832ffdc2abc31cbb..7972c41d8cc212683cced24f1c18a646e968ea6c 100644 (file)
@@ -2568,6 +2568,22 @@ expand0(Type *t, int followptr)
                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);
        if(u != T) {
                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,
                // the method does not exist for value types.
                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'])
                                yyerror("interface pointer mismatch");
                        *m = im;
index 64d2ae65d0d7fe554d944c4b74724a8ead8f56ed..efb092ab81b6ba5609861abc24447e3231ba5f4e 100644 (file)
@@ -192,6 +192,7 @@ implicitstar(Node **nn)
        case TMAP:
        case TSTRING:
        case TARRAY:
+       case TINTER:
                break;
        default:
                return;
@@ -1611,8 +1612,10 @@ lookdot(Node *n, Type *t)
                n->right = f1->nname;           // substitute real name
                n->xoffset = f1->width;
                n->type = f1->type;
-               if(t->etype == TINTER)
+               if(t->etype == TINTER) {
+                       implicitstar(&n->left);
                        n->op = ODOTINTER;
+               }
                return 1;
        }
 
@@ -1742,7 +1745,7 @@ loop:
                if(l != N || r != T)
                        yyerror("assignment count mismatch: %d = %d",
                                listcount(*nl), structcount(*nr));
-                       
+
                return rev(nn);
        }