compiler: check for pkg nilness, fix #3202

Unfortunately, when import cycle happens somewhere deep in the import chain we
dont't get an error from packages.Load(). But it leaves some imports
uninitialized, so at least we can check for them.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
Roman Khimov 2023-11-21 19:31:31 +03:00
parent fced6a27ba
commit eade327b9b
6 changed files with 70 additions and 1 deletions

View file

@ -282,7 +282,14 @@ func (c *codegen) visitPkg(pkg *packages.Package, seen map[string]bool) {
return return
} }
for _, imp := range pkg.Types.Imports() { for _, imp := range pkg.Types.Imports() {
c.visitPkg(pkg.Imports[imp.Path()], seen) var subpkg = pkg.Imports[imp.Path()]
if subpkg == nil {
if c.prog.Err == nil {
c.prog.Err = fmt.Errorf("failed to load %q package from %q, import cycle?", imp.Path(), pkg.PkgPath)
}
return
}
c.visitPkg(subpkg, seen)
} }
seen[pkg.PkgPath] = true seen[pkg.PkgPath] = true
c.packages = append(c.packages, pkg.PkgPath) c.packages = append(c.packages, pkg.PkgPath)

View file

@ -2209,6 +2209,9 @@ func (c *codegen) newLambda(u uint16, lit *ast.FuncLit) {
func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error { func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error {
c.mainPkg = pkg c.mainPkg = pkg
c.analyzePkgOrder() c.analyzePkgOrder()
if c.prog.Err != nil {
return c.prog.Err
}
c.fillDocumentInfo() c.fillDocumentInfo()
funUsage := c.analyzeFuncAndGlobalVarUsage() funUsage := c.analyzeFuncAndGlobalVarUsage()
if c.prog.Err != nil { if c.prog.Err != nil {

View file

@ -2,7 +2,11 @@ package compiler_test
import ( import (
"math/big" "math/big"
"strings"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/stretchr/testify/require"
) )
func TestImportFunction(t *testing.T) { func TestImportFunction(t *testing.T) {
@ -61,3 +65,27 @@ func TestImportNameSameAsOwn(t *testing.T) {
}` }`
eval(t, src, big.NewInt(3)) eval(t, src, big.NewInt(3))
} }
func TestImportCycleDirect(t *testing.T) {
src := `
package some
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2"
func Main() int {
return pkg2.A
}
`
_, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil)
require.Error(t, err)
}
func TestImportCycleIndirect(t *testing.T) {
src := `
package some
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg1"
func Main() int {
return pkg1.A
}
`
_, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil)
require.Error(t, err)
}

View file

@ -0,0 +1,9 @@
package pkg1
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2"
var A int
func init() {
pkg2.A = 1
}

View file

@ -0,0 +1,11 @@
package pkg2
import (
"github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg3"
)
var A int
func init() {
pkg3.A = 2
}

View file

@ -0,0 +1,11 @@
package pkg3
import (
"github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2"
)
var A int
func init() {
pkg2.A = 1
}