mirror of https://github.com/golang/go.git
go/go2go: cache type instantiations
Change-Id: Ie239e6ac7cfabf472970cd2aeddf337bcc242043
This commit is contained in:
parent
a480c1b795
commit
9ceb91ef5f
|
|
@ -14,13 +14,15 @@ import (
|
|||
// We can look them up either with a types.Object associated with an ast.Ident,
|
||||
// or with a types.TypeParam.
|
||||
type typeArgs struct {
|
||||
types []types.Type // type arguments in order
|
||||
toAST map[types.Object]ast.Expr
|
||||
toTyp map[*types.TypeParam]types.Type
|
||||
}
|
||||
|
||||
// newTypeArgs returns a new typeArgs value.
|
||||
func newTypeArgs() *typeArgs {
|
||||
func newTypeArgs(typeTypes []types.Type) *typeArgs {
|
||||
return &typeArgs{
|
||||
types: typeTypes,
|
||||
toAST: make(map[types.Object]ast.Expr),
|
||||
toTyp: make(map[*types.TypeParam]types.Type),
|
||||
}
|
||||
|
|
@ -56,7 +58,7 @@ func (t *translator) instantiateFunction(fnident *ast.Ident, astTypes []ast.Expr
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ta := newTypeArgs()
|
||||
ta := newTypeArgs(typeTypes)
|
||||
for i, tf := range decl.Type.TParams.List {
|
||||
for _, tn := range tf.Names {
|
||||
obj, ok := t.info.Defs[tn]
|
||||
|
|
|
|||
|
|
@ -41,11 +41,12 @@ func isParameterizedFuncDecl(fd *ast.FuncDecl) bool {
|
|||
|
||||
// A translator is used to translate a file from Go with contracts to Go 1.
|
||||
type translator struct {
|
||||
info *types.Info
|
||||
types map[ast.Expr]types.Type
|
||||
idToFunc map[types.Object]*ast.FuncDecl
|
||||
instantiations map[*ast.Ident][]*instantiation
|
||||
newDecls []ast.Decl
|
||||
info *types.Info
|
||||
types map[ast.Expr]types.Type
|
||||
idToFunc map[types.Object]*ast.FuncDecl
|
||||
instantiations map[*ast.Ident][]*instantiation
|
||||
newDecls []ast.Decl
|
||||
typeInstantiations map[types.Type][]*typeInstantiation
|
||||
}
|
||||
|
||||
// An instantiation is a single instantiation of a function.
|
||||
|
|
@ -54,6 +55,12 @@ type instantiation struct {
|
|||
decl *ast.Ident
|
||||
}
|
||||
|
||||
// A typeInstantiation is a single instantiation of a type.
|
||||
type typeInstantiation struct {
|
||||
types []types.Type
|
||||
typ types.Type
|
||||
}
|
||||
|
||||
// rewrite rewrites the contents of one file.
|
||||
func rewriteFile(dir string, fset *token.FileSet, info *types.Info, idToFunc map[types.Object]*ast.FuncDecl, filename string, file *ast.File) (err error) {
|
||||
if err := rewriteAST(info, idToFunc, file); err != nil {
|
||||
|
|
@ -86,10 +93,11 @@ func rewriteFile(dir string, fset *token.FileSet, info *types.Info, idToFunc map
|
|||
// rewriteAST rewrites the AST for a file.
|
||||
func rewriteAST(info *types.Info, idToFunc map[types.Object]*ast.FuncDecl, file *ast.File) (err error) {
|
||||
t := translator{
|
||||
info: info,
|
||||
types: make(map[ast.Expr]types.Type),
|
||||
idToFunc: idToFunc,
|
||||
instantiations: make(map[*ast.Ident][]*instantiation),
|
||||
info: info,
|
||||
types: make(map[ast.Expr]types.Type),
|
||||
idToFunc: idToFunc,
|
||||
instantiations: make(map[*ast.Ident][]*instantiation),
|
||||
typeInstantiations: make(map[types.Type][]*typeInstantiation),
|
||||
}
|
||||
return t.translate(file)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,26 @@ func (t *translator) setType(e ast.Expr, nt types.Type) {
|
|||
|
||||
// instantiateType instantiates typ using ta.
|
||||
func (t *translator) instantiateType(ta *typeArgs, typ types.Type) types.Type {
|
||||
if insts, ok := t.typeInstantiations[typ]; ok {
|
||||
for _, inst := range insts {
|
||||
if t.sameTypes(ta.types, inst.types) {
|
||||
return inst.typ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ityp := t.doInstantiateType(ta, typ)
|
||||
typinst := &typeInstantiation{
|
||||
types: ta.types,
|
||||
typ: ityp,
|
||||
}
|
||||
t.typeInstantiations[typ] = append(t.typeInstantiations[typ], typinst)
|
||||
return ityp
|
||||
}
|
||||
|
||||
// doInstantiateType does the work of instantiating typ using ta.
|
||||
// This should only be called from instantiateType.
|
||||
func (t *translator) doInstantiateType(ta *typeArgs, typ types.Type) types.Type {
|
||||
switch typ := typ.(type) {
|
||||
case *types.TypeParam:
|
||||
if instType, ok := ta.typ(typ); ok {
|
||||
|
|
|
|||
Loading…
Reference in New Issue