interp: enable declaration errors detection at parsing time

The Go parser is able to detect some (but not all) (re-)decleration errors,
if the DeclarationErrors flag is enabled, which was not done so far.

This PR therefore enables that flag, which allows the removal of some of
the now unneeded code that was recently added to support redeclarations.

Fixes #811
This commit is contained in:
mpl
2020-08-28 14:36:00 +02:00
committed by GitHub
parent cb0f3a77bb
commit 535e7e1c42
5 changed files with 7 additions and 47 deletions

View File

@@ -12,4 +12,5 @@ func main() {
}
// Error:
// ../_test/redeclaration-global5.go:5:1: time redeclared in this block
// ../_test/redeclaration-global5.go:5:6: time redeclared in this block
// previous declaration at ../_test/redeclaration-global5.go:3:5

View File

@@ -365,7 +365,7 @@ func wrapInMain(src string) string {
// interpreter's FileSet.
func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error) {
var inFunc bool
var mode parser.Mode
mode := parser.DeclarationErrors
// Allow incremental parsing of declarations or statements, by inserting
// them in a pseudo file package or function. Those statements or

View File

@@ -386,12 +386,6 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
return false
}
if _, exists := sc.sym[typeName]; exists {
// TODO(mpl): find the exact location of the previous declaration
err = n.cfgErrorf("%s redeclared in this block", typeName)
return false
}
if n.child[1].kind == identExpr {
n.typ = &itype{cat: aliasT, val: typ, name: typeName}
} else {
@@ -1781,18 +1775,6 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
// Global object allocation is already performed in GTA.
index = sc.sym[c.ident].index
} else {
if sym, exists := sc.sym[c.ident]; exists {
if sym.typ.node != nil &&
sym.typ.node.anc != nil {
// for non-predeclared identifiers (struct, map, etc)
prevDecl := n.interp.fset.Position(sym.typ.node.anc.pos)
err = n.cfgErrorf("%s redeclared in this block\n\tprevious declaration at %v", c.ident, prevDecl)
return
}
// for predeclared identifiers (int, string, etc)
err = n.cfgErrorf("%s redeclared in this block", c.ident)
return
}
index = sc.add(n.typ)
sc.sym[c.ident] = &symbol{index: index, kind: varSym, typ: n.typ}
}

View File

@@ -110,21 +110,12 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
}
for _, c := range n.child[:l] {
asImportName := filepath.Join(c.ident, baseName)
sym1, exists1 := sc.sym[asImportName]
sym2, exists2 := sc.sym[c.ident]
if !exists1 && !exists2 {
sym, exists := sc.sym[asImportName]
if !exists {
sc.sym[c.ident] = &symbol{index: sc.add(n.typ), kind: varSym, global: true, typ: n.typ, node: n}
continue
}
var sym *symbol
if exists1 {
// prev declaration is an import statement
sym = sym1
} else {
// prev declaration is whatever else (var, type, etc)
sym = sym2
}
// redeclaration error
if sym.typ.node != nil && sym.typ.node.anc != nil {
prevDecl := n.interp.fset.Position(sym.typ.node.anc.pos)
@@ -142,7 +133,6 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
ident := n.child[1].ident
switch {
case isMethod(n):
// TODO(mpl): redeclaration detection
// Add a method symbol in the receiver type name space
var rcvrtype *itype
n.ident = ident
@@ -179,19 +169,6 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
sym, exists := sc.sym[ident]
if exists {
// Make sure the symbol we found seems to be about another node, before calling
// it a redeclaration.
if sym.typ.isComplete() {
// TODO(mpl): this check might be too permissive?
if sym.kind != funcSym || sym.typ.cat != n.typ.cat || sym.node != n || sym.index != -1 {
// redeclaration error
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
}
}
// Add a function symbol in the package name space except for init
sc.sym[n.child[1].ident] = &symbol{kind: funcSym, typ: n.typ, node: n, index: -1}
}
@@ -235,7 +212,7 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e
break
}
// redeclaration error
// redeclaration error. Not caught by the parser.
err = n.cfgErrorf("%s redeclared in this block", name)
return false
}

View File

@@ -821,7 +821,7 @@ func TestMultiEvalNoName(t *testing.T) {
_, err = i.Eval(string(data))
if k == 1 {
expectedErr := fmt.Errorf("3:8: fmt/%s redeclared in this block", interp.DefaultSourceName)
if err.Error() != expectedErr.Error() {
if err == nil || err.Error() != expectedErr.Error() {
t.Fatalf("unexpected result; wanted error %v, got %v", expectedErr, err)
}
return