aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/noder/reader.go')
-rw-r--r--src/cmd/compile/internal/noder/reader.go69
1 files changed, 48 insertions, 21 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 83979a91c8..5481812b18 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -2125,16 +2125,32 @@ func usedLocals(body []ir.Node) ir.NameSet {
// method wrappers.
var needWrapperTypes []*types.Type
-func (r *reader) needWrapper(typ *types.Type) *types.Type {
- // TODO(mdempsky): Be more judicious about generating wrappers.
- // For now, generating all possible wrappers is simple and correct,
- // but potentially wastes a lot of time/space.
+// haveWrapperTypes lists types for which we know we already have
+// method wrappers, because we found the type in an imported package.
+var haveWrapperTypes []*types.Type
+func (r *reader) needWrapper(typ *types.Type) *types.Type {
if typ.IsPtr() {
base.Fatalf("bad pointer type: %v", typ)
}
- needWrapperTypes = append(needWrapperTypes, typ)
+ // If a type was found in an imported package, then we can assume
+ // that package (or one of its transitive dependencies) already
+ // generated method wrappers for it.
+ //
+ // Exception: If we're instantiating an imported generic type or
+ // function, we might be instantiating it with type arguments not
+ // previously seen before.
+ //
+ // TODO(mdempsky): Distinguish when a generic function or type was
+ // instantiated in an imported package so that we can add types to
+ // haveWrapperTypes instead.
+ if r.p != localPkgReader && !r.hasTypeParams() {
+ haveWrapperTypes = append(haveWrapperTypes, typ)
+ } else {
+ needWrapperTypes = append(needWrapperTypes, typ)
+ }
+
return typ
}
@@ -2143,21 +2159,33 @@ func (r *reader) wrapTypes(target *ir.Package) {
r.needWrapper(types.ErrorType)
seen := make(map[string]*types.Type)
- for _, typ := range needWrapperTypes {
- if typ.Sym() == nil {
- key := typ.LinkString()
- if prev := seen[key]; prev != nil {
- if !types.Identical(typ, prev) {
- base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key)
- }
- continue
+ addType := func(typ *types.Type) bool {
+ if typ.Sym() != nil {
+ return true
+ }
+
+ key := typ.LinkString()
+ if prev := seen[key]; prev != nil {
+ if !types.Identical(typ, prev) {
+ base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key)
}
- seen[key] = typ
+ return false
}
- r.wrapType(typ, target)
+ seen[key] = typ
+ return true
}
+ for _, typ := range haveWrapperTypes {
+ addType(typ)
+ }
+ haveWrapperTypes = nil
+
+ for _, typ := range needWrapperTypes {
+ if addType(typ) {
+ r.wrapType(typ, target)
+ }
+ }
needWrapperTypes = nil
}
@@ -2243,12 +2271,6 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ
assert(!sym.Uniq())
sym.SetUniq(true)
- // TODO(mdempsky): Fix typecheck to not depend on creation of
- // imported method value wrappers.
- if false && !reflectdata.NeedEmit(tbase) {
- return
- }
-
// TODO(mdempsky): Use method.Pos instead?
pos := base.AutogeneratedPos
@@ -2258,6 +2280,11 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ
// Declare and initialize variable holding receiver.
recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
+ if !reflectdata.NeedEmit(tbase) {
+ typecheck.Func(fn)
+ return
+ }
+
addTailCall(pos, fn, recv, method)
r.finishWrapperFunc(fn, target)