diff --git a/cl/compile.go b/cl/compile.go index 8115f58b06..be1c35a24f 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -32,6 +32,7 @@ import ( "github.com/xgo-dev/llgo/cl/blocks" "github.com/xgo-dev/llgo/cl/ssawrap" + "github.com/xgo-dev/llgo/internal/genmethod" "github.com/xgo-dev/llgo/internal/goembed" "github.com/xgo-dev/llgo/internal/typepatch" "golang.org/x/tools/go/ssa" @@ -370,6 +371,9 @@ func (p *context) compileMethodsIf(pkg llssa.Package, typ types.Type, keep func( mthds := prog.MethodSets.MethodSet(typ) for i, n := 0, mthds.Len(); i < n; i++ { mthd := mthds.At(i) + if genmethod.SupportsGenericMethods && genmethod.IsGenericMethod(mthd.Type()) { + continue + } if ssaMthd := p.methodValue(mthd); ssaMthd != nil { if keep != nil && !keep(ssaMthd) { continue diff --git a/cl/import.go b/cl/import.go index e7c2d38b40..fdca28ea96 100644 --- a/cl/import.go +++ b/cl/import.go @@ -30,6 +30,7 @@ import ( "github.com/xgo-dev/llgo/internal/directive" "github.com/xgo-dev/llgo/internal/env" + "github.com/xgo-dev/llgo/internal/genmethod" "github.com/xgo-dev/llgo/internal/locality" llssa "github.com/xgo-dev/llgo/ssa" ) @@ -555,6 +556,11 @@ func funcName(pkg *types.Package, fn *ssa.Function, org bool) string { // will diverge for promoted unexported methods. if method, ok := fn.Object().(*types.Func); ok { fnName = llssa.MethodSymbolName(pkg, method, fnName) + if genmethod.SupportsGenericMethods && genmethod.IsGenericMethod(method.Type()) { + if targs := fn.TypeArgs(); len(targs) > 0 { + fnName += llssa.TypeArgs(targs) + } + } } // Synthesized $thunk/$bound functions have no Object. Their references // are produced through this same funcName path, so the wrapper name is diff --git a/cl/instr.go b/cl/instr.go index 7ad03c48a7..f01bf1dec0 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -30,6 +30,7 @@ import ( "golang.org/x/tools/go/ssa" + "github.com/xgo-dev/llgo/internal/genmethod" llssa "github.com/xgo-dev/llgo/ssa" ) @@ -1476,7 +1477,11 @@ func collectRuntimeCallerMethods(pkg *ssa.Package, runtimeTypes []types.Type) [] addMethods := func(typ types.Type) { methodSet := pkg.Prog.MethodSets.MethodSet(typ) for i := 0; i < methodSet.Len(); i++ { - fn := pkg.Prog.MethodValue(methodSet.At(i)) + meth := methodSet.At(i) + if genmethod.SupportsGenericMethods && genmethod.IsGenericMethod(meth.Type()) { + continue + } + fn := pkg.Prog.MethodValue(meth) if fn != nil && !seen[fn] { seen[fn] = true methods = append(methods, fn) @@ -1788,6 +1793,9 @@ func (a *runtimeCallerAnalysis) methodTargetsForType(typ types.Type, method *typ if sel.Obj().Name() != method.Name() { continue } + if genmethod.SupportsGenericMethods && genmethod.IsGenericMethod(sel.Type()) { + continue + } fn := a.pkg.Prog.MethodValue(sel) if fn == nil { return nil, false diff --git a/internal/genmethod/method.go b/internal/genmethod/method.go new file mode 100644 index 0000000000..63ffa92e8e --- /dev/null +++ b/internal/genmethod/method.go @@ -0,0 +1,5 @@ +//go:build !go1.27 + +package genmethod + +const SupportsGenericMethods = false diff --git a/internal/genmethod/method_go127.go b/internal/genmethod/method_go127.go new file mode 100644 index 0000000000..700c43f7be --- /dev/null +++ b/internal/genmethod/method_go127.go @@ -0,0 +1,5 @@ +//go:build go1.27 + +package genmethod + +const SupportsGenericMethods = true diff --git a/internal/genmethod/types.go b/internal/genmethod/types.go new file mode 100644 index 0000000000..93e8c409aa --- /dev/null +++ b/internal/genmethod/types.go @@ -0,0 +1,7 @@ +package genmethod + +import "go/types" + +func IsGenericMethod(typ types.Type) bool { + return typ.(*types.Signature).TypeParams().Len() > 0 +} diff --git a/ssa/abitype.go b/ssa/abitype.go index dc0f7de24d..ed77589c4e 100644 --- a/ssa/abitype.go +++ b/ssa/abitype.go @@ -24,6 +24,7 @@ import ( "go/types" "sort" + "github.com/xgo-dev/llgo/internal/genmethod" "github.com/xgo-dev/llgo/ssa/abi" "github.com/xgo-dev/llvm" ) @@ -571,6 +572,9 @@ func (b Builder) abiInterfaceMethods(mset *types.MethodSet) []*types.Selection { methods := make([]*types.Selection, 0, n) for i := 0; i < n; i++ { m := mset.At(i) + if genmethod.SupportsGenericMethods && genmethod.IsGenericMethod(m.Type()) { + continue + } fn, _ := m.Obj().(*types.Func) if b.Prog.isNoInterfaceMethod(fn) { continue