Skip to content

feat(instrument): Integrate go/types for accurate escape analysis (Phase 2C) #23

@kolkov

Description

@kolkov

Summary

Integrate Go's type checker (go/types) to perform accurate escape analysis and eliminate false positives on stack-local variables.

Problem

Our current AST-based heuristics cannot determine with 100% accuracy which variables escape to the heap. Only go/types can provide:

  1. Full type information - Know exact types, not just syntax
  2. Scope resolution - Track variable definitions across packages
  3. Interface satisfaction - Know when value escapes via interface{}
  4. Closure capture - Detect variables captured by closures

Solution

Architecture

Source Files → go/types.Config.Check() → types.Info
                                              ↓
                                         types.Info.Defs
                                         types.Info.Uses
                                         types.Info.Types
                                              ↓
                              instrumentVisitor with type info

Implementation

// In cmd/racedetector/instrument/instrument.go

import (
    "go/types"
    "golang.org/x/tools/go/packages"
)

func instrumentPackage(pkgPath string) error {
    cfg := &packages.Config{
        Mode: packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo,
    }
    pkgs, err := packages.Load(cfg, pkgPath)
    if err != nil {
        return err
    }
    
    for _, pkg := range pkgs {
        for _, file := range pkg.Syntax {
            visitor := &instrumentVisitor{
                typeInfo: pkg.TypesInfo,
                // ... other fields
            }
            ast.Walk(visitor, file)
        }
    }
}

type instrumentVisitor struct {
    typeInfo *types.Info
    // ...
}

func (v *instrumentVisitor) shouldInstrument(ident *ast.Ident) bool {
    obj := v.typeInfo.ObjectOf(ident)
    if obj == nil {
        return true // Conservative: instrument if unknown
    }
    
    // Check if variable escapes
    if v.doesEscape(obj) {
        return true
    }
    
    return false
}

Escape Detection

  1. Variable captured in closure → escapes
  2. Passed to function expecting interface{} → might escape
  3. Address taken and stored in heap object → escapes
  4. Returned from function → escapes

Benefits of go/types

Feature AST-only With go/types
Named returns
Parameters
Loop variables ⚠️ heuristic ✅ accurate
Local variables ⚠️ heuristic ✅ accurate
Closure captures
Interface escapes

Acceptance Criteria

  • Integration with go/types.Check
  • Use types.Info for variable tracking
  • Accurate escape analysis for local variables
  • Handle cross-package references
  • Handle closure variable captures
  • Handle interface{} escapes
  • Unit tests with complex escape scenarios
  • Zygomys: zero false positives on stack-local variables
  • Performance: < 2x increase in instrumentation time

Estimated Effort

2-4 weeks

Related

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions