Skip to content

Commit

Permalink
Fix for nested non-builtin call expression in map access (#245)
Browse files Browse the repository at this point in the history
This PR refines the logic of non-literal map access, particularly in the
case of built-in call expressions, to not consider the index trackable
if there exists a nested call to non-trackable expression (e.g., custom
function) from inside the built-in function.

For example, 
```
type MessageBlock struct{}

func (m *MessageBlock) Messages() []*int {
	return []*int{new(int)}
}

func test(msgSet []*MessageBlock) {
	for _, msgBlock := range msgSet {
		_ = *msgBlock.Messages()[len(msgBlock.Messages())-1]
	}
}
```
the `test` function was taking 7 iterations to converge, while now after
the fix it requires only 3 iterations.

Note: the goal of this PR is to improve performance only, and should not
have any effect on the reported errors.
  • Loading branch information
sonalmahajan15 authored May 21, 2024
1 parent 482b433 commit a27654d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
10 changes: 9 additions & 1 deletion assertion/function/assertiontree/parse_expr_producer.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,15 @@ func (r *RootAssertionNode) ParseExprAsProducer(expr ast.Expr, doNotTrack bool)
return false
case *ast.CallExpr:
if fun, ok := index.Fun.(*ast.Ident); ok {
return r.isBuiltIn(fun)
if r.isBuiltIn(fun) {
// iterate over the arguments of the call expression
for _, arg := range index.Args {
if !isIndexTrackable(arg) {
return false
}
}
return true
}
}
return false
case *ast.SelectorExpr:
Expand Down
14 changes: 14 additions & 0 deletions assertion/function/testdata/src/go.uber.org/backprop/fixpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,17 @@ func testAssignmentInLoop(m mapType, key string) { // expect_fixpoint: 6 2 4
}
}
}

// test map access with nested non-builtin call expression in the index expression

type MessageBlock struct{}

func (m *MessageBlock) Messages() []*int {
return []*int{new(int)}
}

func testNonBuiltinNestedIndex(msgSet []*MessageBlock) { // expect_fixpoint: 3 1 4
for _, msgBlock := range msgSet {
_ = *msgBlock.Messages()[len(msgBlock.Messages())-1]
}
}

0 comments on commit a27654d

Please sign in to comment.