{"record":{"id":"d2a45a63a9bc3ae7","repo":"vitessio/vitess","slug":"interface-s-implemented-by-s-s-as-t-without","errorCode":null,"errorMessage":"interface %s implemented by %s (%s as %T) without ptr","messagePattern":"interface (.+?) implemented by (.+?) \\((.+?) as %T\\) without ptr","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/tools/asthelpergen/asthelpergen.go","lineNumber":175,"sourceCode":"\t}\n}\n\nfunc findImplementations(scope *types.Scope, iff *types.Interface, impl func(types.Type) error) error {\n\tconst onlyReferences = false\n\n\tfor _, name := range scope.Names() {\n\t\tobj := scope.Lookup(name)\n\t\tif _, ok := obj.(*types.TypeName); !ok {\n\t\t\tcontinue\n\t\t}\n\t\tbaseType := obj.Type()\n\t\tif types.Implements(baseType, iff) {\n\t\t\tif onlyReferences {\n\t\t\t\tswitch tt := baseType.Underlying().(type) {\n\t\t\t\tcase *types.Interface:\n\t\t\t\t\t// This is OK; interfaces are references\n\t\t\t\tdefault:\n\t\t\t\t\treturn fmt.Errorf(\"interface %s implemented by %s (%s as %T) without ptr\", iff.String(), baseType, tt.String(), tt)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif types.TypeString(baseType, noQualifier) == visitableName {\n\t\t\t\t// skip the visitable interface\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := impl(baseType); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tpointerT := types.NewPointer(baseType)\n\t\tif types.Implements(pointerT, iff) {\n\t\t\tif err := impl(pointerT); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/tools/asthelpergen/asthelpergen.go#L157-L193","documentation":"asthelpergen walks all types that implement a target interface and, when onlyReferences is set, requires every implementing type to be a pointer or an interface (reference types). This error is thrown when a value (non-pointer) concrete type implements the interface, which the generators cannot emit helpers for. The message names the interface, the implementing type, and its underlying kind.","triggerScenarios":"Running GenerateASTHelpers for an interface where a struct (or other non-reference underlying type) implements the interface by value while onlyReferences=true is configured, e.g. `type MyStruct struct{...}` with value-receiver methods satisfying e.g. SQLNode.","commonSituations":"A developer adds a new AST type with value receivers; refactoring moves methods from pointer receivers to value receivers; generating helpers for a new interface without auditing all implementers.","solutions":["Change the implementing type's methods to pointer receivers and use *T wherever the interface is required","Remove the value-type implementer from the package set passed via options.Packages if it should not be generated","If references are not actually required, set onlyReferences=false in the generator Options"],"exampleFix":"// before\nfunc (n Ident) SQLNode() {}\n// after\nfunc (n *Ident) SQLNode() {}","handlingStrategy":"validation","validationCode":"types := collector.Implementations(interfaceName)\nfor _, t := range types {\n    if _, isPtr := t.(*types.Pointer); !isPtr {\n        if _, isIface := t.Underlying().(*types.Interface); !isIface {\n            return fmt.Errorf(\"value type %s implements %s; use pointer receiver\", t, interfaceName)\n        }\n    }\n}","typeGuard":"func isReferenceType(t types.Type) bool {\n    switch t.Underlying().(type) {\n    case *types.Interface, *types.Pointer:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Always define AST node methods with pointer receivers","Audit implementers of an interface (golang.org/x/tools `implements` or gopls) before generating helpers","Run asthelpergen in CI so violations are caught on the PR"],"tags":["codegen","go-types","ast-helper-gen"],"backgroundTag":"non-pointer-interface-implementer","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}