Skip to content

Commit d8e94f2

Browse files
committed
internal/refactor/inline: fix bug in shadow detection
There's a kink in the scope tree at Func{Decl,Lit} that we forgot to straighten out in all cases. Fixed, with test. Change-Id: Iaed9636b4cc17537af6b607b153f8b4183ac7cb7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/531699 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 0adbf9c commit d8e94f2

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

internal/refactor/inline/callee.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ func analyzeParams(logf func(string, ...any), fset *token.FileSet, info *types.I
472472
// for the reference.
473473
func addShadows(shadows map[string]bool, info *types.Info, exclude string, stack []ast.Node) map[string]bool {
474474
for _, n := range stack {
475-
if scope, ok := info.Scopes[n]; ok {
475+
if scope := scopeFor(info, n); scope != nil {
476476
for _, name := range scope.Names() {
477477
if name != exclude {
478478
if shadows == nil {

internal/refactor/inline/inline.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,12 +1536,7 @@ func createBindingDecl(logf func(string, ...any), caller *Caller, args []*argume
15361536
func (caller *Caller) lookup(name string) types.Object {
15371537
pos := caller.Call.Pos()
15381538
for _, n := range caller.path {
1539-
// The function body scope (containing not just params)
1540-
// is associated with FuncDecl.Type, not FuncDecl.Body.
1541-
if decl, ok := n.(*ast.FuncDecl); ok {
1542-
n = decl.Type
1543-
}
1544-
if scope := caller.Info.Scopes[n]; scope != nil {
1539+
if scope := scopeFor(caller.Info, n); scope != nil {
15451540
if _, obj := scope.LookupParent(name, pos); obj != nil {
15461541
return obj
15471542
}
@@ -1550,6 +1545,18 @@ func (caller *Caller) lookup(name string) types.Object {
15501545
return nil
15511546
}
15521547

1548+
func scopeFor(info *types.Info, n ast.Node) *types.Scope {
1549+
// The function body scope (containing not just params)
1550+
// is associated with the function's type, not body.
1551+
switch fn := n.(type) {
1552+
case *ast.FuncDecl:
1553+
n = fn.Type
1554+
case *ast.FuncLit:
1555+
n = fn.Type
1556+
}
1557+
return info.Scopes[n]
1558+
}
1559+
15531560
// -- predicates over expressions --
15541561

15551562
// freeVars returns the names of all free identifiers of e:

internal/refactor/inline/inline_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,17 @@ func TestSubstitution(t *testing.T) {
401401
`func _() { var local int; f(local) }`,
402402
`func _() { var local int; _ = local }`,
403403
},
404+
{
405+
"Regression test for detection of shadowing in nested functions.",
406+
`func f(x int) { _ = func() { y := 1; print(y); print(x) } }`,
407+
`func _(y int) { f(y) } `,
408+
`func _(y int) {
409+
{
410+
var x int = y
411+
_ = func() { y := 1; print(y); print(x) }
412+
}
413+
}`,
414+
},
404415
})
405416
}
406417

0 commit comments

Comments
 (0)