if r.p.exportVersion < iexportVersionGenerics {
errorf("unexpected type param type")
}
- name0, sub := parseSubscript(name)
- tn := types2.NewTypeName(pos, r.currPkg, name0, nil)
- t := types2.NewTypeParam(tn, nil)
- if sub == 0 {
- errorf("missing subscript")
+ // Remove the "path" from the type param name that makes it unique
+ ix := strings.LastIndex(name, ".")
+ if ix < 0 {
+ errorf("missing path for type param")
}
- t.SetId(sub)
+ tn := types2.NewTypeName(pos, r.currPkg, name[ix+1:], nil)
+ t := types2.NewTypeParam(tn, nil)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
id := ident{r.currPkg.Name(), name}
n, _ := typ.(*types2.Named)
return n
}
-
-func parseSubscript(name string) (string, uint64) {
- // Extract the subscript value from the type param name. We export
- // and import the subscript value, so that all type params have
- // unique names.
- sub := uint64(0)
- startsub := -1
- for i, r := range name {
- if '₀' <= r && r < '₀'+10 {
- if startsub == -1 {
- startsub = i
- }
- sub = sub*10 + uint64(r-'₀')
- }
- }
- if startsub >= 0 {
- name = name[:startsub]
- }
- return name, sub
-}
}
func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
+ // Set g.curDecl to the function name, as context for the type params declared
+ // during types2-to-types1 translation if this is a generic function.
+ g.curDecl = decl.Name.Value
+ obj2 := g.info.Defs[decl.Name]
+ recv := types2.AsSignature(obj2.Type()).Recv()
+ if recv != nil {
+ t2 := deref2(recv.Type())
+ // This is a method, so set g.curDecl to recvTypeName.methName instead.
+ g.curDecl = types2.AsNamed(t2).Obj().Name() + "." + g.curDecl
+ }
+
fn := ir.NewFunc(g.pos(decl))
fn.Nname, _ = g.def(decl.Name)
fn.Nname.Func = fn
}
func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
+ // Set g.curDecl to the type name, as context for the type params declared
+ // during types2-to-types1 translation if this is a generic type.
+ g.curDecl = decl.Name.Value
if decl.Alias {
name, _ := g.def(decl.Name)
g.pragmaFlags(decl.Pragma, 0)
methods := make([]*types.Field, otyp.NumMethods())
for i := range methods {
m := otyp.Method(i)
+ // Set g.curDecl to recvTypeName.methName, as context for the
+ // method-specific type params in the receiver.
+ g.curDecl = decl.Name.Value + "." + m.Name()
meth := g.obj(m)
methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
methods[i].Nname = meth
// avoid adding closures of generic functions/methods to the target.Decls
// list.
topFuncIsGeneric bool
+
+ // The context during type/function/method declarations that is used to
+ // uniquely name type parameters. We need unique names for type params so we
+ // can be sure they match up correctly between types2-to-types1 translation
+ // and types1 importing.
+ curDecl string
}
func (g *irgen) later(fn func()) {
// Save the name of the type parameter in the sym of the type.
// Include the types2 subscript in the sym name
pkg := g.tpkg(typ)
- sym := pkg.Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" }))
+ // Create the unique types1 name for a type param, using its context with a
+ // function, type, or method declaration.
+ nm := g.curDecl + "." + typ.Obj().Name()
+ sym := pkg.Lookup(nm)
if sym.Def != nil {
// Make sure we use the same type param type for the same
// name, whether it is created during types1-import or
meth2 = ir.NewNameAt(meth.Pos(), newsym)
rparams := types2.AsSignature(m.Type()).RecvTypeParams()
tparams := make([]*types.Type, rparams.Len())
+ // Set g.curDecl to be the method context, so type
+ // params in the receiver of the method that we are
+ // translating gets the right unique name.
+ g.curDecl = typ.Obj().Name() + "." + m.Name()
for i := range tparams {
tparams[i] = g.typ1(rparams.At(i))
}
return t.index
}
-// SetId sets the unique id of a type param. Should only be used for type params
-// in imported generic types.
-func (t *TypeParam) SetId(id uint64) {
- t.id = id
-}
-
// Constraint returns the type constraint specified for t.
func (t *TypeParam) Constraint() Type {
return t.bound
break
}
// Optionally write out package for typeparams (like Named).
- // TODO(danscales): this is required for import/export, so
- // we maybe need a separate function that won't be changed
- // for debugging purposes.
if t.obj.pkg != nil {
writePackage(w.buf, t.obj.pkg, w.qf)
}
"io"
"math/big"
"sort"
+ "strings"
)
type intReader struct {
if r.p.exportVersion < iexportVersionGenerics {
errorf("unexpected type param type")
}
- name0, sub := parseSubscript(name)
- tn := types.NewTypeName(pos, r.currPkg, name0, nil)
- t := types.NewTypeParam(tn, nil)
- if sub == 0 {
- errorf("missing subscript")
+ // Remove the "path" from the type param name that makes it unique
+ ix := strings.LastIndex(name, ".")
+ if ix < 0 {
+ errorf("missing path for type param")
}
-
- // TODO(rfindley): can we use a different, stable ID?
- // t.SetId(sub)
-
+ tn := types.NewTypeName(pos, r.currPkg, name[ix+1:], nil)
+ t := types.NewTypeParam(tn, nil)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
id := ident{r.currPkg.Name(), name}
n, _ := typ.(*types.Named)
return n
}
-
-func parseSubscript(name string) (string, uint64) {
- // Extract the subscript value from the type param name. We export
- // and import the subscript value, so that all type params have
- // unique names.
- sub := uint64(0)
- startsub := -1
- for i, r := range name {
- if '₀' <= r && r < '₀'+10 {
- if startsub == -1 {
- startsub = i
- }
- sub = sub*10 + uint64(r-'₀')
- }
- }
- if startsub >= 0 {
- name = name[:startsub]
- }
- return name, sub
-}