}
// instantiateMethods instantiates all the methods (and associated dictionaries) of
-// all fully-instantiated generic types that have been added to g.instTypeList.
+// all fully-instantiated generic types that have been added to typecheck.instTypeList.
+// It continues until no more types are added to typecheck.instTypeList.
func (g *irgen) instantiateMethods() {
- for i := 0; i < len(g.instTypeList); i++ {
- typ := g.instTypeList[i]
- assert(!typ.HasShape())
- // Mark runtime type as needed, since this ensures that the
- // compiler puts out the needed DWARF symbols, when this
- // instantiated type has a different package from the local
- // package.
- typecheck.NeedRuntimeType(typ)
- // Lookup the method on the base generic type, since methods may
- // not be set on imported instantiated types.
- baseSym := typ.OrigSym()
- baseType := baseSym.Def.(*ir.Name).Type()
- for j, _ := range typ.Methods().Slice() {
- if baseType.Methods().Slice()[j].Nointerface() {
- typ.Methods().Slice()[j].SetNointerface(true)
+ for {
+ instTypeList := typecheck.GetInstTypeList()
+ if len(instTypeList) == 0 {
+ break
+ }
+ for _, typ := range instTypeList {
+ assert(!typ.HasShape())
+ // Mark runtime type as needed, since this ensures that the
+ // compiler puts out the needed DWARF symbols, when this
+ // instantiated type has a different package from the local
+ // package.
+ typecheck.NeedRuntimeType(typ)
+ // Lookup the method on the base generic type, since methods may
+ // not be set on imported instantiated types.
+ baseSym := typ.OrigSym()
+ baseType := baseSym.Def.(*ir.Name).Type()
+ for j, _ := range typ.Methods().Slice() {
+ if baseType.Methods().Slice()[j].Nointerface() {
+ typ.Methods().Slice()[j].SetNointerface(true)
+ }
+ baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
+ // Eagerly generate the instantiations and dictionaries that implement these methods.
+ // We don't use the instantiations here, just generate them (and any
+ // further instantiations those generate, etc.).
+ // Note that we don't set the Func for any methods on instantiated
+ // types. Their signatures don't match so that would be confusing.
+ // Direct method calls go directly to the instantiations, implemented above.
+ // Indirect method calls use wrappers generated in reflectcall. Those wrappers
+ // will use these instantiations if they are needed (for interface tables or reflection).
+ _ = g.getInstantiation(baseNname, typ.RParams(), true)
+ _ = g.getDictionarySym(baseNname, typ.RParams(), true)
}
- baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
- // Eagerly generate the instantiations and dictionaries that implement these methods.
- // We don't use the instantiations here, just generate them (and any
- // further instantiations those generate, etc.).
- // Note that we don't set the Func for any methods on instantiated
- // types. Their signatures don't match so that would be confusing.
- // Direct method calls go directly to the instantiations, implemented above.
- // Indirect method calls use wrappers generated in reflectcall. Those wrappers
- // will use these instantiations if they are needed (for interface tables or reflection).
- _ = g.getInstantiation(baseNname, typ.RParams(), true)
- _ = g.getDictionarySym(baseNname, typ.RParams(), true)
}
}
- g.instTypeList = nil
-
}
// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated.
}
ir.CurFunc = savef
- // Add any new, fully instantiated types seen during the substitution to
- // g.instTypeList.
- g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
if doubleCheck {
ir.Visit(newf, func(n ir.Node) {
off: off,
}
g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay)
- g.instTypeList = append(g.instTypeList, subst.InstTypeList...)
return sym
}
objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA)
infoPrint("=== Finalized dictionary %s\n", d.sym.Name)
-
- g.instTypeList = append(g.instTypeList, subst.InstTypeList...)
}
g.dictSymsToFinalize = nil
}
base.Assert(p)
}
+// List of newly fully-instantiated types who should have their methods generated.
+var instTypeList []*types.Type
+
+// NeedInstType adds a new fully-instantied type to instTypeList.
+func NeedInstType(t *types.Type) {
+ instTypeList = append(instTypeList, t)
+}
+
+// GetInstTypeList returns the current contents of instTypeList, and sets
+// instTypeList to nil.
+func GetInstTypeList() []*types.Type {
+ r := instTypeList
+ instTypeList = nil
+ return r
+}
+
// General type substituter, for replacing typeparams with type args.
type Tsubster struct {
Tparams []*types.Type
// If non-nil, the substitution map from name nodes in the generic function to the
// name nodes in the new stenciled function.
Vars map[*ir.Name]*ir.Name
- // New fully-instantiated generic types whose methods should be instantiated.
- InstTypeList []*types.Type
// If non-nil, function to substitute an incomplete (TFORW) type.
SubstForwFunc func(*types.Type) *types.Type
}
newt.Methods().Set(newfields)
if !newt.HasTParam() && !newt.HasShape() {
// Generate all the methods for a new fully-instantiated type.
- ts.InstTypeList = append(ts.InstTypeList, newt)
+
+ NeedInstType(newt)
}
}
return newt
--- /dev/null
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+import (
+ "reflect"
+ "sync"
+)
+
+type addressableValue struct{ reflect.Value }
+
+type arshalers[Options, Coder any] struct {
+ fncVals []typedArshaler[Options, Coder]
+ fncCache sync.Map // map[reflect.Type]unmarshaler
+}
+type typedArshaler[Options, Coder any] struct {
+ typ reflect.Type
+ fnc func(Options, *Coder, addressableValue) error
+}
+
+type UnmarshalOptions1 struct {
+ // Unmarshalers is a list of type-specific unmarshalers to use.
+ Unmarshalers *arshalers[UnmarshalOptions1, Decoder1]
+}
+
+type Decoder1 struct {
+}
+
+func (a *arshalers[Options, Coder]) lookup(fnc func(Options, *Coder, addressableValue) error, t reflect.Type) func(Options, *Coder, addressableValue) error {
+ return fnc
+}
+
+func UnmarshalFuncV2[T any](fn func(UnmarshalOptions1, *Decoder1, T) error) *arshalers[UnmarshalOptions1, Decoder1] {
+ return &arshalers[UnmarshalOptions1, Decoder1]{}
+}