From: Robert Griesemer Date: Wed, 17 Aug 2016 22:35:15 +0000 (-0700) Subject: go/types: fix scope extents for range and type switch variables X-Git-Tag: go1.8beta1~1789 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fd8028dec92166545d080de99021c9c51f05c670;p=gostls13.git 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/27290 Reviewed-by: Matthew Dempsky --- diff --git a/doc/go_spec.html b/doc/go_spec.html index 731186e66b..4ce75e4f88 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index e011e6daef..1d74612dc0 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -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) diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index b8c89a0afa..4e423bd686 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -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 {