typesutil

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package typesutil exposes small, dependency-light helpers around go/types for test and tool code in this module.

Boundary with tools/archtest/internal/typeseval:

  • typeseval is archtest-internal (SharedResolver, build-tag matrix, generated-path skip, etc.) and lives under internal/ so it cannot be imported from outside tools/archtest.
  • typesutil is non-internal and importable from any _test.go in the module (archtest rules, kernel/* tests).

Constraints:

  • stdlib + golang.org/x/tools only.
  • No runtime/cells/adapters imports.
  • Each helper does one go/types operation.

ref: golang.org/x/tools/go/types/typeutil StaticCallee ref: golang.org/x/tools/internal/typesinternal ReceiverNamed (pattern source; the upstream package is internal and unimportable)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ImplementsInterface

func ImplementsInterface(t types.Type, iface *types.Interface) bool

ImplementsInterface reports whether t — as a value OR via its pointer — satisfies iface. It mirrors the go/types.Implements(V, T) argument shape and adds the value-or-pointer convenience: a value type may satisfy iface only through its pointer method set, so when the value form does not implement and t is not already a pointer, the *t form is tried. The pointer wrap is skipped when t is already a *types.Pointer (a **T method set adds nothing over *T).

Use ImplementsInterfaceExact when the no-pointer-fallback semantic is intentional — e.g. t may itself be an interface type and a synthetic pointer-to-interface check would be meaningless.

Signature note: the previously-proposed (typesInfo, expr, ifaceObj) shape was deliberately rejected — none of the consolidated call sites hold an ast.Expr at the point of check (they take a struct field, obj.Type(), or a parameter type). This shape mirrors stdlib go/types.Implements(V, T).

AI-robust note: the ImplementsInterface vs ImplementsInterfaceExact choice is a name-level (Medium) distinction — both share one signature, so picking the wrong one is not a compile error. The fixture-level guard is the discriminating test case in implements_interface_test.go. The Hard layer (banning raw go/types.Implements outside this file) is enforced by archtest TYPESUTIL-IMPLEMENTS-FUNNEL-01 (tools/archtest/implements_funnel_test.go).

Edge cases (covered by implements_interface_test.go):

  • value-receiver impl / pointer-receiver-only impl via value / via *T
  • t already *types.Pointer (true path, no double-wrap)
  • t already *types.Pointer and non-impl (no **T fallback)
  • promoted (embedded) interface methods
  • generic instantiated named types
  • non-impl / nil t / nil iface

ref: golang.org/x/tools go/analysis/passes/copylock (types.Implements +

pointer-receiver method-set idiom)

func ImplementsInterfaceExact

func ImplementsInterfaceExact(t types.Type, iface *types.Interface) bool

ImplementsInterfaceExact is the strict, value-only satisfaction check — the deliberate no-pointer-fallback counterpart of ImplementsInterface. Use it where t may itself be an interface type and a synthetic pointer-to-interface check would be semantically meaningless (e.g. the CELL-RAW-INFRA-PUBLIC-OPTION-PARAM-01 anonymous-interface bypass detector, where t is frequently a *types.Interface).

This file is the sole sanctioned site for raw go/types.Implements. The archtest TYPESUTIL-IMPLEMENTS-FUNNEL-01 (tools/archtest/implements_funnel_test.go) rejects any go/types.Implements reference — call, dot-import, import-alias, or func-value — anywhere else; route every interface-satisfaction check through ImplementsInterface / ImplementsInterfaceExact instead.

func ResolveCallee

func ResolveCallee(typesInfo *types.Info, call *ast.CallExpr) (fn *types.Func, named *types.Named, isPtr bool, ok bool)

ResolveCallee returns the static method callee together with its receiver's named type for a method call. This is the canonical resolver for archtest / governance rules that need both pieces — typically the signature (for parameter / return type checks) AND the receiver named type (for owner-package or specific-type checks).

Returns ok=false in the same cases as ResolveReceiverType: builtins, interface dispatch, package-level functions, method values, methods on anonymous receivers.

Callers that only need the named receiver type should use ResolveReceiverType; this entry point exists so callers needing the signature don't pay a second typeutil.StaticCallee lookup.

func ResolveReceiverType

func ResolveReceiverType(typesInfo *types.Info, call *ast.CallExpr) (named *types.Named, isPtr bool, ok bool)

ResolveReceiverType returns the named receiver type for a method call, e.g. (*scanner.Scanner) for s.EachInSubtree(...). It returns ok=false for any call that cannot be statically resolved to a method on a named type:

  • builtins (StaticCallee returns nil)
  • interface dispatch (StaticCallee filters interfaceMethod)
  • package-level functions (Signature.Recv() is nil)
  • method values (the call expression's Fun is a variable, not a Selector)
  • methods on anonymous/unnamed types (no *types.Named to return)

The isPtr return distinguishes pointer- and value-receiver methods. Callers that only care about the named type may discard isPtr.

Edge cases:

  • Promoted (embedded) methods return the embedded type's *types.Named, not the outer type. This mirrors what StaticCallee resolves to.
  • Generic methods return the generic base *types.Named, not the instantiation. Callers needing instantiation info call TypeArgs() on the returned named type.
  • Alias-pointer chains (`type P = *T; func (P) M()`) unalias before the pointer cast, matching upstream typesinternal.ReceiverNamed.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL