diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index b9af878599..1bcfd420c6 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -154,6 +154,7 @@ struct Type uchar outnamed; Type* method; + Type* xmethod; Sym* sym; int32 vargen; // unique name for OTYPE/ONAME diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index 2e2e68c8bf..7338743246 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -145,7 +145,7 @@ methods(Type *t) a = nil; o = 0; oldlist = nil; - for(f=mt->method; f; f=f->down) { + for(f=mt->xmethod; f; f=f->down) { if(f->type->etype != TFUNC) continue; if(f->etype != TFIELD) @@ -159,6 +159,8 @@ methods(Type *t) // this is not an embedded pointer inside a struct, // method does not apply. this = getthisx(f->type)->type->type; + if(isptr[this->etype] && this->type == t) + continue; if(isptr[this->etype] && !isptr[t->etype] && f->embedded != 2 && !isifacemethod(f)) continue; @@ -200,7 +202,7 @@ methods(Type *t) if(!eqtype(this, t)) { if(oldlist == nil) oldlist = pc; - if(isptr[it->etype] && isptr[this->etype] + if(isptr[t->etype] && isptr[this->etype] && f->embedded && !isifacemethod(f)) genembedtramp(t, f, a->tsym); else diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index d922c8b019..a1c66d1179 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -2796,7 +2796,7 @@ expandmeth(Sym *s, Type *t) if(s == S) return; - if(t == T) + if(t == T || t->xmethod != nil) return; // generate all reachable methods @@ -2818,6 +2818,7 @@ expandmeth(Sym *s, Type *t) } } + t->xmethod = t->method; for(sl=slist; sl!=nil; sl=sl->link) { if(sl->good) { // add it to the base type method list @@ -2826,8 +2827,8 @@ expandmeth(Sym *s, Type *t) f->embedded = 1; // needs a trampoline if(sl->followptr) f->embedded = 2; - f->down = t->method; - t->method = f; + f->down = t->xmethod; + t->xmethod = f; } }