From 0c7119464ec064e1fa16cc862f4d9f2ec8526a2f Mon Sep 17 00:00:00 2001 From: visualfc Date: Fri, 26 Jan 2024 09:44:09 +0800 Subject: [PATCH] hide TyOverloadNamed to sig --- ast.go | 7 ++++--- func_ext.go | 2 +- type_ext.go | 25 ++++++++++++++++++++++++- typeparams.go | 2 +- typeparams_test.go | 2 +- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ast.go b/ast.go index 25fb356e..27a9a5ae 100644 --- a/ast.go +++ b/ast.go @@ -697,9 +697,10 @@ retry: case *TyInstruction: return t.instr.Call(pkg, args, flags, fn.Src) case *TypeType: // type convert - return matchTypeCast(pkg, t.Type(), fn, args, flags) - case *TyOverloadNamed: - return matchOverloadNamedTypeCast(pkg, t.Obj, fn.Src, args, flags) + if on, ok := CheckOverloadNamed(t.typ); ok { + return matchOverloadNamedTypeCast(pkg, on.Obj, fn.Src, args, flags) + } + return matchTypeCast(pkg, t.typ, fn, args, flags) case *types.Named: fnType = pkg.cb.getUnderlying(t) goto retry diff --git a/func_ext.go b/func_ext.go index 2f9fdbb2..a2267509 100644 --- a/func_ext.go +++ b/func_ext.go @@ -58,7 +58,7 @@ const ( ) // sigFuncEx return func type ($overloadArgs ...interface{$overloadMethod()}) -func sigFuncEx(pkg *types.Package, recv *types.Var, t TyFuncEx) *types.Signature { +func sigFuncEx(pkg *types.Package, recv *types.Var, t types.Type) *types.Signature { sig := types.NewSignatureType(types.NewVar(token.NoPos, nil, "", t), nil, nil, nil, nil, false) typ := types.NewInterfaceType([]*types.Func{ types.NewFunc(token.NoPos, nil, overloadMethod, sig), diff --git a/type_ext.go b/type_ext.go index 2bcb1461..0eeaa35d 100644 --- a/type_ext.go +++ b/type_ext.go @@ -105,11 +105,34 @@ func (p *TyOverloadNamed) String() string { func NewOverloadNamed(pos token.Pos, pkg *types.Package, name string, typs ...*types.Named) *types.TypeName { t := &TyOverloadNamed{Types: typs} - o := types.NewTypeName(pos, pkg, name, t) + sig := sigFuncEx(pkg, nil, t) + o := types.NewTypeName(pos, pkg, name, sig) t.Obj = o return o } +// CheckOverloadNamed returns if specified type is a TyOverloadNamed or not. +func CheckOverloadNamed(typ types.Type) (*TyOverloadNamed, bool) { + switch sig := typ.(type) { + case *TyOverloadNamed: + return sig, true + case *types.Signature: + if sig.Params().Len() == 1 { + if param := sig.Params().At(0); param.Name() == overloadArgs { + if typ, ok := param.Type().(*types.Interface); ok && typ.NumMethods() == 1 { + if sig, ok := typ.Method(0).Type().(*types.Signature); ok { + if recv := sig.Recv(); recv != nil { + t, ok := recv.Type().(*TyOverloadNamed) + return t, ok + } + } + } + } + } + } + return nil, false +} + type TyInstruction struct { instr Instruction } diff --git a/typeparams.go b/typeparams.go index 39a3fab2..26cd0588 100644 --- a/typeparams.go +++ b/typeparams.go @@ -471,7 +471,7 @@ func (p *Package) Instantiate(orig types.Type, targs []types.Type, src ...ast.No p.cb.ensureLoaded(targ) } ctxt := p.cb.ctxt - if on, ok := orig.(*TyOverloadNamed); ok { + if on, ok := CheckOverloadNamed(orig); ok { var first error for _, t := range on.Types { ret, err := types.Instantiate(ctxt, t, targs, true) diff --git a/typeparams_test.go b/typeparams_test.go index 226cb6d3..69b56757 100644 --- a/typeparams_test.go +++ b/typeparams_test.go @@ -60,7 +60,7 @@ func Gopx_Var_Cast__1[T map[string]any]() *Var__1[T] { scope := pkgRef.Types.Scope() log.Println("==> Lookup", scope.Lookup("Var__0")) objVar := pkgRef.Ref("Var") - on, ok := objVar.Type().(*gox.TyOverloadNamed) + on, ok := gox.CheckOverloadNamed(objVar.Type()) if !ok { t.Fatal("TestOverloadNamed: not TyOverloadNamed?") }