| Index: src/cmd/gc/typecheck.c |
| =================================================================== |
| --- a/src/cmd/gc/typecheck.c |
| +++ b/src/cmd/gc/typecheck.c |
| @@ -1491,8 +1491,10 @@ |
| if(t->etype == TSTRUCT || t->etype == TINTER) |
| f1 = lookdot1(s, t, t->type, dostrcmp); |
| + tt = n->left->type; |
| + |
| f2 = T; |
| - if(n->left->type == t || n->left->type->sym == S) { |
| + if(tt == t || tt->sym == S || (n->op == ODOTPTR && tt->type == t)) { |
| f2 = methtype(t); |
| if(f2 != T) { |
| // Use f2->method, not f2->xmethod: adddot has |
| @@ -1510,7 +1512,7 @@ |
| n->xoffset = f1->width; |
| n->type = f1->type; |
| if(t->etype == TINTER) { |
| - if(isptr[n->left->type->etype]) { |
| + if(isptr[tt->etype]) { |
| n->left = nod(OIND, n->left, N); // implicitstar |
| typecheck(&n->left, Erv); |
| } |
| @@ -1520,7 +1522,6 @@ |
| } |
| if(f2 != T) { |
| - tt = n->left->type; |
| dowidth(tt); |
| rcvr = getthisx(f2->type)->type->type; |
| if(!eqtype(rcvr, tt)) { |
| @@ -1534,6 +1535,15 @@ |
| n->left = nod(OIND, n->left, N); |
| n->left->implicit = 1; |
| typecheck(&n->left, Etype|Erv); |
| + } else if (tt->etype == tptr && rcvr->etype == tptr && |
| + eqtype(tt->type, rcvr->type)) { |
| + checklvalue(n->left, "call pointer method on"); |
| + addrescapes(n->left); |
| + n->left = nod(OIND, n->left, N); |
| + n->left->implicit = 1; |
| + n->left = nod(OADDR, n->left, N); |
| + n->left->implicit = 1; |
| + typecheck(&n->left, Etype|Erv); |
| } else { |
| // method is attached to wrong type? |
| fatal("method mismatch: %T for %T", rcvr, tt); |