From 38091b20215dfce08afaabe2a8dbf410761c4483 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 30 Oct 2024 21:02:08 +0800 Subject: [PATCH] ssa: func Instantiate --- cl/builtin_test.go | 17 +++++++++++++++++ cl/compile.go | 19 ++++++------------- ssa/type_cvt.go | 23 ++++++++++++++--------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/cl/builtin_test.go b/cl/builtin_test.go index e468a4ec..d9fbc3fb 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -345,3 +345,20 @@ func TestContextResolveLinkname(t *testing.T) { }) } } + +func TestInstantiate(t *testing.T) { + obj := types.NewTypeName(0, nil, "T", nil) + named := types.NewNamed(obj, types.Typ[types.Int], nil) + if typ := obj.Type(); typ != instantiate(typ, named) { + t.Fatal("error") + } + tparam := types.NewTypeParam(types.NewTypeName(0, nil, "P", nil), types.NewInterface(nil, nil)) + named.SetTypeParams([]*types.TypeParam{tparam}) + inamed, err := types.Instantiate(nil, named, []types.Type{types.Typ[types.Int]}, true) + if err != nil { + t.Fatal(err) + } + if typ := instantiate(obj.Type(), inamed.(*types.Named)); typ == obj.Type() || typ.(*types.Named).TypeArgs() == nil { + t.Fatal("error") + } +} diff --git a/cl/compile.go b/cl/compile.go index 750e7bf8..7e25497c 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -1036,19 +1036,7 @@ func (p *context) patchType(typ types.Type) types.Type { if pkg := o.Pkg(); typepatch.IsPatched(pkg) { if patch, ok := p.patches[pkg.Path()]; ok { if obj := patch.Types.Scope().Lookup(o.Name()); obj != nil { - otyp := obj.Type() - if tp := t.TypeArgs(); tp != nil { - targs := make([]types.Type, tp.Len()) - for i := 0; i < tp.Len(); i++ { - targs[i] = tp.At(i) - } - var err error - otyp, err = types.Instantiate(nil, obj.Type(), targs, true) - if err != nil { - panic(fmt.Errorf("patchType error: %v", err)) - } - } - return p.prog.Type(otyp, llssa.InGo).RawType() + return p.prog.Type(instantiate(obj.Type(), t), llssa.InGo).RawType() } } } @@ -1056,6 +1044,11 @@ func (p *context) patchType(typ types.Type) types.Type { return typ } +func instantiate(orig types.Type, t *types.Named) (typ types.Type) { + typ, _ = llssa.Instantiate(orig, t) + return +} + func (p *context) resolveLinkname(name string) string { if link, ok := p.prog.Linkname(name); ok { prefix, ltarget, _ := strings.Cut(link, ".") diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index c5862ffd..cfefe227 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -148,15 +148,7 @@ func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { p.typs[unsafe.Pointer(t)] = unsafe.Pointer(t) if tund, cvt := p.cvtType(t.Underlying()); cvt { named.SetUnderlying(tund) - if tp := t.TypeArgs(); tp != nil { - targs := make([]types.Type, tp.Len()) - for i := 0; i < tp.Len(); i++ { - targs[i] = tp.At(i) - } - typ, err := types.Instantiate(nil, named, targs, true) - if err != nil { - panic(fmt.Errorf("cvtNamed error: %v", err)) - } + if typ, ok := Instantiate(named, t); ok { named = typ.(*types.Named) } p.typs[unsafe.Pointer(t)] = unsafe.Pointer(named) @@ -165,6 +157,19 @@ func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) { return t, false } +func Instantiate(orig types.Type, t *types.Named) (types.Type, bool) { + if tp := t.TypeArgs(); tp != nil { + targs := make([]types.Type, tp.Len()) + for i := 0; i < tp.Len(); i++ { + targs[i] = tp.At(i) + } + if typ, err := types.Instantiate(nil, orig, targs, true); err == nil { + return typ, true + } + } + return orig, false +} + func (p goTypes) cvtClosure(sig *types.Signature) *types.Struct { ctx := types.NewParam(token.NoPos, nil, closureCtx, types.Typ[types.UnsafePointer]) raw := p.cvtFunc(sig, ctx)