Skip to content

Commit

Permalink
support inline directive at anonymous function assignments
Browse files Browse the repository at this point in the history
The `//gcassert:inline` directive can now be used at assignments of
anonymous functions to local variables.
  • Loading branch information
mgartner committed Jan 3, 2025
1 parent c0b40bf commit fe6ce04
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 14 deletions.
21 changes: 16 additions & 5 deletions gcassert.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,25 @@ func (v *assertVisitor) Visit(node ast.Node) ast.Visitor {
continue
}
if directive == inline {
// If the node is a FuncDecl or an assignment of an
// anonymous function, add the ident's Object to our map of
// must-inline functions.
var obj types.Object
switch n := node.(type) {
case *ast.FuncDecl:
// Add the Object that this FuncDecl's ident is connected
// to our map of must-inline functions.
obj := v.p.TypesInfo.Defs[n.Name]
if obj != nil {
v.mustInlineFuncs[obj] = struct{}{}
obj = v.p.TypesInfo.Defs[n.Name]
case *ast.AssignStmt:
if _, ok := n.Rhs[0].(*ast.FuncLit); !ok {
break
}
id, ok := n.Lhs[0].(*ast.Ident)
if !ok {
break
}
obj = v.p.TypesInfo.Defs[id]
}
if obj != nil {
v.mustInlineFuncs[obj] = struct{}{}
continue
}
}
Expand Down
22 changes: 13 additions & 9 deletions gcassert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@ func badDirective3() {
23: {directives: []assertDirective{bce}},
},
"testdata/inline.go": {
45: {inlinableCallsites: []passInfo{{colNo: 15}}},
49: {directives: []assertDirective{inline}},
51: {directives: []assertDirective{inline}},
55: {directives: []assertDirective{inline}},
57: {inlinableCallsites: []passInfo{{colNo: 36}}},
58: {inlinableCallsites: []passInfo{{colNo: 35}}},
75: {directives: []assertDirective{inline}},
77: {directives: []assertDirective{inline}},
45: {inlinableCallsites: []passInfo{{colNo: 15}}},
49: {directives: []assertDirective{inline}},
51: {directives: []assertDirective{inline}},
55: {directives: []assertDirective{inline}},
57: {inlinableCallsites: []passInfo{{colNo: 36}}},
58: {inlinableCallsites: []passInfo{{colNo: 35}}},
85: {inlinableCallsites: []passInfo{{colNo: 21}}},
86: {inlinableCallsites: []passInfo{{colNo: 26}}},
88: {directives: []assertDirective{inline}},
90: {directives: []assertDirective{inline}},
102: {inlinableCallsites: []passInfo{{colNo: 12}}},
},
"testdata/noescape.go": {
11: {directives: []assertDirective{noescape}},
Expand Down Expand Up @@ -122,7 +125,8 @@ testdata/inline.go:55: sum += 1: call was not inlined
testdata/inline.go:58: test(0).neverInlinedMethod(10): call was not inlined
testdata/inline.go:60: otherpkg.A{}.NeverInlined(sum): call was not inlined
testdata/inline.go:62: otherpkg.NeverInlinedFunc(sum): call was not inlined
testdata/inline.go:77: sum += anonNeverInlinedNoAssert(i): call was not inlined
testdata/inline.go:86: anonNeverInlined(i): call was not inlined
testdata/inline.go:90: sum += anonNeverInlinedNoAssert(i): call was not inlined
testdata/issue5.go:4: Gen().Layout(): call was not inlined
`

Expand Down
39 changes: 39 additions & 0 deletions testdata/inline.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,58 @@ func caller() {

otherpkg.NeverInlinedFunc(sum)

//gcassert:inline
anonInlined := func(a int) int {
return a + 10
}

anonInlinedNoAssert := func(a int) int {
return a + 10
}

//gcassert:inline
anonNeverInlined := func(a int) int {
fmt.Println(a)
return a + 10
}

anonNeverInlinedNoAssert := func(a int) int {
fmt.Println(a)
return a + 10
}

for i := 0; i < 10; i++ {
sum += anonInlined(i)
sum += anonNeverInlined(i)
//gcassert:inline
sum += anonInlinedNoAssert(i)
//gcassert:inline
sum += anonNeverInlinedNoAssert(i)
}

// The assertion for the anonymous function assigned to baz below does not
// apply to this call of the named function baz, which cannot be inlined and
// has no inline assertion.
sum += baz(1)

// gcassert:inline
baz := func(a int) int {
return a + 10
}
sum += baz(1)

{
// The assertion for the baz in the parent scope does not apply to this
// baz, which cannot be inlined and has no assertion.
baz := func(a int) int {
fmt.Println(a)
return a + 10
}
sum += baz(1)
}
}

//go:noinline
func baz(a int) int {
return a + 10
}

0 comments on commit fe6ce04

Please sign in to comment.