Commit fd8028de authored by Robert Griesemer's avatar Robert Griesemer

go/types: fix scope extents for range and type switch variables

The changes match the existing compilers, and assume an adjusted
spec (per issue #16794).

Fixes #15686.

Change-Id: I72677ce75888c41a8f3c2963117a2f2d5501c42b
Reviewed-on: https://go-review.googlesource.com/27290Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 604efe12
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of May 31, 2016",
"Subtitle": "Version of August 18, 2016",
"Path": "/ref/spec"
}-->
......
......@@ -1016,7 +1016,11 @@ func TestScopeLookupParent(t *testing.T) {
}
var info Info
makePkg := func(path string, files ...*ast.File) {
imports[path], _ = conf.Check(path, fset, files, &info)
var err error
imports[path], err = conf.Check(path, fset, files, &info)
if err != nil {
t.Fatal(err)
}
}
makePkg("lib", mustParse("package lib; var X int"))
......@@ -1024,17 +1028,44 @@ func TestScopeLookupParent(t *testing.T) {
// name at that point and checks that it resolves to a decl of
// the specified kind and line number. "undef" means undefined.
mainSrc := `
/*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/
package main
import "lib"
var Y = lib.X
func f() {
print(Y) /*Y=var:4*/
z /*z=undef*/ := /*z=undef*/ 1 /*z=var:7*/
print(z)
/*f=func:5*/ /*lib=pkgname:3*/
type /*T=undef*/ T /*T=typename:10*/ *T
import . "lib"
const Pi = 3.1415
type T struct{}
var Y, _ = lib.X, X
func F(){
const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/
type /*t=undef*/ t /*t=typename:14*/ *t
print(Y) /*Y=var:10*/
x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y
var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
var a []int
for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
var i interface{}
switch y := i.(type) { /*y=undef*/
case /*y=undef*/ int /*y=var:23*/ :
case float32, /*y=undef*/ float64 /*y=var:23*/ :
default /*y=var:23*/:
println(y)
}
/*y=undef*/
switch int := i.(type) {
case /*int=typename:0*/ int /*int=var:31*/ :
println(int)
default /*int=var:31*/ :
}
}
/*main=undef*/
`
info.Uses = make(map[*ast.Ident]Object)
f := mustParse(mainSrc)
makePkg("main", f)
......
......@@ -628,9 +628,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
T = x.typ
}
obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
scopePos := clause.End()
if len(clause.Body) > 0 {
scopePos = clause.Body[0].Pos()
scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0)
if n := len(clause.List); n > 0 {
scopePos = clause.List[n-1].End()
}
check.declare(check.scope, nil, obj, scopePos)
check.recordImplicit(clause, obj)
......@@ -822,12 +822,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// declare variables
if len(vars) > 0 {
scopePos := s.X.End()
for _, obj := range vars {
// spec: "The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
// for short variable declarations) and ends at the end of the innermost
// containing block."
scopePos := s.End()
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
}
} else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment