aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2026-04-06 13:28:55 -0400
committerGopher Robot <gobot@golang.org>2026-04-06 11:51:51 -0700
commitad7d6071ac1955e76e7407d8345cf18f354a1693 (patch)
tree74e00648bcc080f655973be720b9d16ed9955837
parenta91083291cd7ea07cd766b7c71b889f476cf3084 (diff)
downloadgo-ad7d6071ac1955e76e7407d8345cf18f354a1693.tar.xz
cmd/compile/internal/importer: consume generic methods in importer
Change-Id: Iac9428fe8d2fb3e6fde30940470bf5d3ac9751cb Reviewed-on: https://go-review.googlesource.com/c/go/+/763141 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Mark Freeman <markfreeman@google.com>
-rw-r--r--src/cmd/compile/internal/importer/ureader.go88
1 files changed, 62 insertions, 26 deletions
diff --git a/src/cmd/compile/internal/importer/ureader.go b/src/cmd/compile/internal/importer/ureader.go
index b9ef31bb0e..1ad7a83d87 100644
--- a/src/cmd/compile/internal/importer/ureader.go
+++ b/src/cmd/compile/internal/importer/ureader.go
@@ -72,8 +72,10 @@ type reader struct {
}
type readerDict struct {
- bounds []typeInfo
+ rtbounds []typeInfo
+ rtparams []*types2.TypeParam
+ tbounds []typeInfo
tparams []*types2.TypeParam
derived []derivedInfo
@@ -262,7 +264,11 @@ func (r *reader) doTyp() (res types2.Type) {
return name.Type()
case pkgbits.TypeTypeParam:
- return r.dict.tparams[r.Len()]
+ n := r.Len()
+ if n < len(r.dict.rtbounds) {
+ return r.dict.rtparams[n]
+ }
+ return r.dict.tparams[n-len(r.dict.rtbounds)]
case pkgbits.TypeArray:
len := int64(r.Uint64())
@@ -421,7 +427,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
pos := r.pos()
var tparams []*types2.TypeParam
if r.Version().Has(pkgbits.AliasTypeParamNames) {
- tparams = r.typeParamNames(false)
+ tparams = r.typeParamNames(false, false)
}
typ := r.typ()
return newAliasTypeName(pr.enableAlias, pos, objPkg, objName, typ, tparams)
@@ -434,15 +440,22 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
case pkgbits.ObjFunc:
pos := r.pos()
- tparams := r.typeParamNames(false)
- sig := r.signature(nil, nil, tparams)
+ var rtparams []*types2.TypeParam
+ var recv *types2.Var
+ if r.Version().Has(pkgbits.GenericMethods) && r.Bool() {
+ r.selector()
+ rtparams = r.typeParamNames(false, true)
+ recv = r.param()
+ }
+ tparams := r.typeParamNames(false, false)
+ sig := r.signature(recv, rtparams, tparams)
return types2.NewFunc(pos, objPkg, objName, sig)
case pkgbits.ObjType:
pos := r.pos()
return types2.NewTypeNameLazy(pos, objPkg, objName, func(_ *types2.Named) ([]*types2.TypeParam, types2.Type, []*types2.Func, []func()) {
- tparams := r.typeParamNames(true)
+ tparams := r.typeParamNames(true, false)
// TODO(mdempsky): Rewrite receiver types to underlying is an
// Interface? The go/types importer does this (I think because
@@ -477,9 +490,20 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits)
}
- dict.bounds = make([]typeInfo, r.Len())
- for i := range dict.bounds {
- dict.bounds[i] = r.typInfo()
+ nreceivers := 0
+ if r.Version().Has(pkgbits.GenericMethods) {
+ nreceivers = r.Len()
+ }
+ nexplicits := r.Len()
+
+ dict.rtbounds = make([]typeInfo, nreceivers)
+ for i := range dict.rtbounds {
+ dict.rtbounds[i] = r.typInfo()
+ }
+
+ dict.tbounds = make([]typeInfo, nexplicits)
+ for i := range dict.tbounds {
+ dict.tbounds[i] = r.typInfo()
}
dict.derived = make([]derivedInfo, r.Len())
@@ -498,14 +522,24 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
return &dict
}
-func (r *reader) typeParamNames(isLazy bool) []*types2.TypeParam {
+func (r *reader) typeParamNames(isLazy bool, isGenMeth bool) []*types2.TypeParam {
r.Sync(pkgbits.SyncTypeParamNames)
// Note: This code assumes there are no implicit type parameters.
// This is fine since it only reads exported declarations, which
// never have implicits.
- if len(r.dict.bounds) == 0 {
+ var in []typeInfo
+ var out *[]*types2.TypeParam
+ if isGenMeth {
+ in = r.dict.rtbounds
+ out = &r.dict.rtparams
+ } else {
+ in = r.dict.tbounds
+ out = &r.dict.tparams
+ }
+
+ if len(in) == 0 {
return nil
}
@@ -514,39 +548,41 @@ func (r *reader) typeParamNames(isLazy bool) []*types2.TypeParam {
// create all the TypeNames and TypeParams, then we construct and
// set the bound type.
- r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds))
- for i := range r.dict.bounds {
+ // We have to save tparams outside of the closure, because typeParamNames
+ // can be called multiple times with the same dictionary instance.
+ tparams := make([]*types2.TypeParam, len(in))
+ *out = tparams
+
+ for i := range in {
pos := r.pos()
pkg, name := r.localIdent()
tname := types2.NewTypeName(pos, pkg, name, nil)
- r.dict.tparams[i] = types2.NewTypeParam(tname, nil)
+ tparams[i] = types2.NewTypeParam(tname, nil)
}
// Type parameters that are read by lazy loaders cannot have their
// constraints set eagerly; do them after loading (go.dev/issue/63285).
if isLazy {
// The reader dictionary will continue mutating before we have time
- // to call delayed functions; must make a local copy of both the type
- // parameters and their (unexpanded) constraints.
- bounds := make([]types2.Type, len(r.dict.bounds))
- for i, bound := range r.dict.bounds {
- bounds[i] = r.p.typIdx(bound, r.dict)
+ // to call delayed functions; make a local copy of the constraints.
+ types := make([]types2.Type, len(in))
+ for i, info := range in {
+ types[i] = r.p.typIdx(info, r.dict)
}
- tparams := r.dict.tparams
r.delayed = append(r.delayed, func() {
- for i, bound := range bounds {
- tparams[i].SetConstraint(bound)
+ for i, typ := range types {
+ tparams[i].SetConstraint(typ)
}
})
} else {
- for i, bound := range r.dict.bounds {
- r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict))
+ for i, info := range in {
+ tparams[i].SetConstraint(r.p.typIdx(info, r.dict))
}
}
- return r.dict.tparams
+ return tparams
}
func (r *reader) method(isLazy bool) *types2.Func {
@@ -554,7 +590,7 @@ func (r *reader) method(isLazy bool) *types2.Func {
pos := r.pos()
pkg, name := r.selector()
- rtparams := r.typeParamNames(isLazy)
+ rtparams := r.typeParamNames(isLazy, false)
sig := r.signature(r.param(), rtparams, nil)
_ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go.