vitessio/vitess · error

interface implemented by ( as %T) without ptr

Error message

interface %s implemented by %s (%s as %T) without ptr

What it means

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.

Solutions

  1. Change the implementing type's methods to pointer receivers and use *T wherever the interface is required
  2. Remove the value-type implementer from the package set passed via options.Packages if it should not be generated
  3. If references are not actually required, set onlyReferences=false in the generator Options

Example fix

// before
func (n Ident) SQLNode() {}
// after
func (n *Ident) SQLNode() {}
Defensive patterns

Strategy: validation

Validate before calling

types := collector.Implementations(interfaceName)
for _, t := range types {
    if _, isPtr := t.(*types.Pointer); !isPtr {
        if _, isIface := t.Underlying().(*types.Interface); !isIface {
            return fmt.Errorf("value type %s implements %s; use pointer receiver", t, interfaceName)
        }
    }
}

Type guard

func isReferenceType(t types.Type) bool {
    switch t.Underlying().(type) {
    case *types.Interface, *types.Pointer:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/d2a45a63a9bc3ae7. Report an issue: GitHub.

Appendix: source

Thrown at go/tools/asthelpergen/asthelpergen.go:175

	}
}

func findImplementations(scope *types.Scope, iff *types.Interface, impl func(types.Type) error) error {
	const onlyReferences = false

	for _, name := range scope.Names() {
		obj := scope.Lookup(name)
		if _, ok := obj.(*types.TypeName); !ok {
			continue
		}
		baseType := obj.Type()
		if types.Implements(baseType, iff) {
			if onlyReferences {
				switch tt := baseType.Underlying().(type) {
				case *types.Interface:
					// This is OK; interfaces are references
				default:
					return fmt.Errorf("interface %s implemented by %s (%s as %T) without ptr", iff.String(), baseType, tt.String(), tt)
				}
			}
			if types.TypeString(baseType, noQualifier) == visitableName {
				// skip the visitable interface
				continue
			}
			if err := impl(baseType); err != nil {
				return err
			}
			continue
		}
		pointerT := types.NewPointer(baseType)
		if types.Implements(pointerT, iff) {
			if err := impl(pointerT); err != nil {
				return err
			}
			continue
		}

View on GitHub (pinned to 01a25a7d17)