go.tools/go/types: x,y:=0,0 is a Use (not Def) of x if it is already defined.
+ test. Fixes golang/go#7827 LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/89600045
This commit is contained in:
parent
1ae1c63748
commit
379e0e7704
|
@ -289,14 +289,13 @@ func (check *checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
|
|||
} else {
|
||||
check.errorf(lhs.Pos(), "cannot assign to %s", lhs)
|
||||
}
|
||||
check.recordUse(ident, alt)
|
||||
} else {
|
||||
// declare new variable, possibly a blank (_) variable
|
||||
obj = NewVar(ident.Pos(), check.pkg, name, nil)
|
||||
if name != "_" {
|
||||
newVars = append(newVars, obj)
|
||||
}
|
||||
}
|
||||
if obj != nil {
|
||||
check.recordDef(ident, obj)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
package types_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -144,3 +146,60 @@ type T struct{} // receiver type after method declaration
|
|||
t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
|
||||
}
|
||||
}
|
||||
|
||||
// This tests that uses of existing vars on the LHS of an assignment
|
||||
// are Uses, not Defs; and also that the (illegal) use of a non-var on
|
||||
// the LHS of an assignment is a Use nonetheless.
|
||||
func TestIssue7827(t *testing.T) {
|
||||
const src = `
|
||||
package p
|
||||
func _() {
|
||||
const w = 1 // defs w
|
||||
x, y := 2, 3 // defs x, y
|
||||
w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
|
||||
_, _, _ = x, y, z // uses x, y, z
|
||||
}
|
||||
`
|
||||
const want = `L3 defs func p._()
|
||||
L4 defs const w untyped int
|
||||
L5 defs var x int
|
||||
L5 defs var y int
|
||||
L6 defs var z int
|
||||
L6 uses const w untyped int
|
||||
L6 uses var x int
|
||||
L7 uses var x int
|
||||
L7 uses var y int
|
||||
L7 uses var z int`
|
||||
|
||||
f, err := parser.ParseFile(fset, "", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// don't abort at the first error
|
||||
conf := Config{Error: func(err error) { t.Log(err) }}
|
||||
defs := make(map[*ast.Ident]Object)
|
||||
uses := make(map[*ast.Ident]Object)
|
||||
_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
|
||||
if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
|
||||
t.Errorf("Check: unexpected error: %s", s)
|
||||
}
|
||||
|
||||
var facts []string
|
||||
for id, obj := range defs {
|
||||
if obj != nil {
|
||||
fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
|
||||
facts = append(facts, fact)
|
||||
}
|
||||
}
|
||||
for id, obj := range uses {
|
||||
fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
|
||||
facts = append(facts, fact)
|
||||
}
|
||||
sort.Strings(facts)
|
||||
|
||||
got := strings.Join(facts, "\n")
|
||||
if got != want {
|
||||
t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue