interp: delete incomplete type on pkg import

When a package is imported, it creates a symbol with a name like "errors/_.go". If a statement such as x := errors.New(...) is executed before import "errors", it creates an incomplete type symbol with a name like "errors". Importing the package after the incomplete type symbol has been created does not fix the compile issue because the incomplete type still exists.

To fix this, this PR deletes the incomplete type symbol, if one exists.

Closes #1388.
This commit is contained in:
Ethan Reesor
2022-04-26 04:04:13 -05:00
committed by GitHub
parent ad9db379e7
commit 4e77fc9436
2 changed files with 29 additions and 0 deletions

View File

@@ -217,6 +217,12 @@ func (interp *Interpreter) gta(root *node, rpath, importPath, pkgName string) ([
if name == "" {
name = interp.pkgNames[ipath]
}
// If an incomplete type exists, delete it
if sym, exists := sc.sym[name]; exists && sym.kind == typeSym && sym.typ.incomplete {
delete(sc.sym, name)
}
// Imports of a same package are all mapped in the same scope, so we cannot just
// map them by their names, otherwise we could have collisions from same-name
// imports in different source files of the same package. Therefore, we suffix

View File

@@ -1751,6 +1751,29 @@ func TestRestrictedEnv(t *testing.T) {
}
}
func TestIssue1388(t *testing.T) {
i := interp.New(interp.Options{Env: []string{"foo=bar"}})
err := i.Use(stdlib.Symbols)
if err != nil {
t.Fatal(err)
}
_, err = i.Eval(`x := errors.New("")`)
if err == nil {
t.Fatal("Expected an error")
}
_, err = i.Eval(`import "errors"`)
if err != nil {
t.Fatal(err)
}
_, err = i.Eval(`x := errors.New("")`)
if err != nil {
t.Fatal(err)
}
}
func TestIssue1383(t *testing.T) {
const src = `
package main