Skip to content

Conversation

@flaticols
Copy link
Owner

Summary

Adds resetgen-analyzer - a static analyzer that detects missing Reset() calls before sync.Pool.Put().

Features

  • Detects sync.Pool.Put(x) without preceding x.Reset()
  • Handles global pools, struct field pools, and wrapped variables
  • Catches bad pool wrapper implementations (e.g., p.p.Put(v) without v.Reset())
  • Works standalone or with go vet -vettool

Installation

go install github.com/flaticols/resetgen/cmd/resetgen-analyzer@latest
# or
go get -tool github.com/flaticols/resetgen/cmd/resetgen-analyzer

Usage

resetgen-analyzer ./...
# or
go vet -vettool=$(which resetgen-analyzer) ./...

Files

  • cmd/resetgen-analyzer/main.go - CLI entry point
  • cmd/resetgen-analyzer/analyzer/ - Core analysis logic with tests
  • Updated README with documentation for both tools

@flaticols flaticols added the minor Minor version bump label Dec 14, 2025
Copilot AI review requested due to automatic review settings December 14, 2025 12:45
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds resetgen-analyzer, a static analysis tool that detects missing Reset() calls before sync.Pool.Put() operations. The analyzer complements the existing resetgen code generator by providing runtime validation of proper pool usage patterns.

Key Changes:

  • Adds static analyzer CLI and core detection logic for sync.Pool misuse patterns
  • Implements variable tracking to match Reset() calls with Pool.Put() operations
  • Includes comprehensive test suite with testdata covering various pool usage scenarios

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
go.mod Adds golang.org/x/tools dependency for analysis framework
go.sum Dependency checksums for new analyzer dependencies
cmd/resetgen-analyzer/main.go CLI entry point using singlechecker for standalone/go vet integration
cmd/resetgen-analyzer/analyzer/analyzer.go Core analysis logic tracking Reset() calls and sync.Pool.Put() operations
cmd/resetgen-analyzer/analyzer/analyzer_test.go Test harness using analysistest framework
cmd/resetgen-analyzer/analyzer/testdata/src/a/a.go Comprehensive test cases covering good/bad pool usage patterns
README.md Documentation for both tools with installation, usage, and examples

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

bufferPool.Put(w.buf) // want "sync.Pool.Put\\(\\) called without Reset\\(\\) on w"
}

// Generic pool wrapper that handles Reset internally - should NOT trigger
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment "should NOT trigger" is misleading. The analyzer currently doesn't analyze the body of genericPool.Put() to see if it calls Reset() internally. The line at 112 doesn't trigger an error only because genericPool is not a sync.Pool type - it's a custom Pool[T] type. The analyzer only checks for direct sync.Pool.Put() calls. This should be clarified in the comment to avoid confusion about what the analyzer actually does versus what it's supposed to do.

Suggested change
// Generic pool wrapper that handles Reset internally - should NOT trigger
// Generic pool wrapper that handles Reset internally.
// NOTE: The analyzer does NOT analyze the body of genericPool.Put() to see if it calls Reset().
// The line below does NOT trigger an error only because genericPool is not a sync.Pool type.
// The analyzer only checks for direct sync.Pool.Put() calls.

Copilot uses AI. Check for mistakes.

buf.data = encodeJSON(buf.data, v)
_, err := dst.Write(buf.data)

Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example has a bug: the buffer is returned to the pool at line 175 without calling buf.Reset() first. This violates the pattern that the resetgen-analyzer is designed to detect. The code should be:

buf.Reset()
bufPool.Put(buf)

Or alternatively, since this uses the generic Pool wrapper that calls Reset() internally (line 152), the comment should clarify that Reset() is handled by the wrapper's Put method.

Suggested change
buf.Reset()

Copilot uses AI. Check for mistakes.
| Global pool | `bufferPool.Put(buf)` without `buf.Reset()` |
| Struct field pool | `s.pool.Put(buf)` without `buf.Reset()` |
| Wrapped variable | `pool.Put(w.buf)` without `w.buf.Reset()` |
| Pool wrapper | `p.p.Put(v)` without `v.Reset()` inside wrapper method |
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Pool wrapper" pattern description is misleading. The current analyzer implementation doesn't actually analyze what happens inside wrapper methods. It only detects direct sync.Pool.Put() calls. So p.p.Put(v) is detected because p.p is a sync.Pool, not because it's inside a wrapper method. The analyzer would flag this even if Reset() was called elsewhere in the same method. Consider clarifying this documentation to accurately reflect what the analyzer does versus what it's intended to catch.

Suggested change
| Pool wrapper | `p.p.Put(v)` without `v.Reset()` inside wrapper method |
| Pool wrapper | `p.p.Put(v)` without `v.Reset()` (analyzer does not check if inside wrapper method or if Reset is called elsewhere) |

Copilot uses AI. Check for mistakes.
@flaticols flaticols merged commit 782b65f into latest Dec 14, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant