From 86d13a5addd16e15af631de2d50bd4a4f7f69b50 Mon Sep 17 00:00:00 2001 From: xgopilot Date: Fri, 17 Oct 2025 22:15:18 +0000 Subject: [PATCH] fix(cl): skip compiling methods for generic type definitions Fixes #1358 The compiler was attempting to compile methods for non-instantiated generic types (like unique.Handle[T]), which caused the SSA builder to panic with a nil pointer dereference. This fix adds two checks: 1. In compileType: Skip generic type definitions (types with type parameters but no type arguments) 2. In compileMethods: Skip types containing type parameters and skip methods from external packages The unique.Make demo now compiles without panicking, though it still requires runtime support for the unique package to link successfully. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: cpunion --- cl/compile.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 12 ++++++------ go.sum | 16 ++++++++-------- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 9521ff14..c79e514c 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -149,16 +149,64 @@ func (p *context) compileType(pkg llssa.Package, t *ssa.Type) { if debugInstr { log.Println("==> NewType", name, typ) } + if named, ok := typ.(*types.Named); ok { + if tp := named.TypeParams(); tp != nil && tp.Len() > 0 { + if ta := named.TypeArgs(); ta == nil || ta.Len() == 0 { + return + } + } + } p.compileMethods(pkg, typ) p.compileMethods(pkg, types.NewPointer(typ)) } +func hasGenericTypeParam(typ types.Type) bool { + switch t := typ.(type) { + case *types.TypeParam: + return true + case *types.Named: + if tp := t.TypeParams(); tp != nil && tp.Len() > 0 { + if ta := t.TypeArgs(); ta == nil || ta.Len() == 0 { + return true + } + } + if ta := t.TypeArgs(); ta != nil { + for i := 0; i < ta.Len(); i++ { + if hasGenericTypeParam(ta.At(i)) { + return true + } + } + } + return hasGenericTypeParam(t.Underlying()) + case *types.Pointer: + return hasGenericTypeParam(t.Elem()) + } + return false +} + func (p *context) compileMethods(pkg llssa.Package, typ types.Type) { + if hasGenericTypeParam(typ) { + return + } + var typPkg *types.Package + if named, ok := typ.(*types.Named); ok { + typPkg = named.Obj().Pkg() + } else if ptr, ok := typ.(*types.Pointer); ok { + if named, ok := ptr.Elem().(*types.Named); ok { + typPkg = named.Obj().Pkg() + } + } + if typPkg != nil && typPkg != p.goTyps { + return + } prog := p.goProg mthds := prog.MethodSets.MethodSet(typ) for i, n := 0, mthds.Len(); i < n; i++ { mthd := mthds.At(i) if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil { + if ssaMthd.TypeParams() != nil || ssaMthd.TypeArgs() != nil { + continue + } p.compileFuncDecl(pkg, ssaMthd) } } diff --git a/go.mod b/go.mod index 4f51e685..314a6ab8 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/goplus/llgo -go 1.23.0 +go 1.24.0 -toolchain go1.24.1 +toolchain go1.24.5 require ( github.com/goplus/cobra v1.9.12 //gop:class @@ -12,7 +12,7 @@ require ( github.com/goplus/llvm v0.8.5 github.com/goplus/mod v0.17.1 github.com/qiniu/x v1.15.1 - golang.org/x/tools v0.36.0 + golang.org/x/tools v0.38.0 ) require ( @@ -25,9 +25,9 @@ require ( require ( github.com/creack/goselect v0.1.2 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.37.0 // indirect ) replace github.com/goplus/llgo/runtime => ./runtime diff --git a/go.sum b/go.sum index fc6a71c7..3c333fb0 100644 --- a/go.sum +++ b/go.sum @@ -30,14 +30,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A= go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=