typeparams

package
v1.19.0-beta2 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2025 License: BSD-2-Clause Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindNestingFunc

func FindNestingFunc(obj types.Object) *types.Func

FindNestingFunc returns the function or method that the given object is nested in. Returns nil if the object was defined at the package level, the position is invalid, or if the object is a function or method.

This may get different results for some specific object types (e.g. receivers, type parameters) depending on the Go version. In go1.19 and earlier, some objects are not nested in the function they are part of the definition of, but in later versions they are.

func HasTypeParams

func HasTypeParams(typ types.Type) bool

HasTypeParams returns true if object defines type parameters.

Note: this function doe not check if the object definition actually uses the type parameters, neither its own, nor from the outer scope.

func SignatureTypeParams

func SignatureTypeParams(sig *types.Signature) *types.TypeParamList

SignatureTypeParams returns receiver type params for methods, or function type params for standalone functions, or nil for non-generic functions and methods.

Types

type Collector

type Collector struct {
	TContext  *types.Context
	Instances *PackageInstanceSets
	// contains filtered or unexported fields
}

Collector scans type-checked AST tree and adds discovered generic type and function instances to the InstanceSet.

Collector will scan non-generic code for any instantiations of generic types or functions and add them to the InstanceSet. Then it will scan generic types and function with discovered sets of type arguments for more instantiations, until no new ones are discovered.

InstanceSet may contain unprocessed instances of generic types and functions, which will be also scanned, for example found in depending packages.

Note that instances of generic type methods are automatically added to the set whenever their receiver type instance is encountered.

func (*Collector) Finish

func (c *Collector) Finish()

Finish will finish the collecting instances by propagating instances of generic types and functions found in generic code. The generic code is rescanned with in an instances context to find internally defined instances.

This should only be called after all the files are scanned.

func (*Collector) Scan

func (c *Collector) Scan(info *types.Info, pkg *types.Package, files ...*ast.File)

Scan package files for generic instances.

type Instance

type Instance struct {
	Object types.Object       // Object to be instantiated.
	TArgs  typesutil.TypeList // Type params to instantiate with.

	// TNest is the type params of the function this object was nested with-in.
	// e.g. In `func A[X any]() { type B[Y any] struct {} }` the `X`
	// from `A` is the context of `B[Y]` thus creating `B[X;Y]`.
	TNest typesutil.TypeList
}

Instance of a generic type or function.

Non-generic objects can be represented as an Instance with zero type params, they are instances of themselves.

func (Instance) IsTrivial

func (i Instance) IsTrivial() bool

IsTrivial returns true if this is an instance of a non-generic object and it is not nested in a generic function.

func (Instance) Recv

func (i Instance) Recv() Instance

Recv returns an instance of the receiver type of a method.

Returns zero value if not a method.

func (Instance) Resolve

func (i Instance) Resolve(tc *types.Context) types.Type

Resolve instantiates and performs a substitution of the instance to get the concrete type or function. This will panic if the instance is not valid, e.g. if there are a different number of type arguments than the type parameters.

If `tc` is non-nil, it de-duplicates the instance against previous instances with the same identity. See types.Instantiate for more info.

Instances of named types may be lazily substituted, meaning the underlying type may not be fully substituted with the type arguments when returned.

This is useful for quickly resolving an instance for a test or for debugging but this uses a temporary Resolver that will not be reused. When resolving several instances in the same context, it is more efficient to use NewResolver to take advantage of caching.

func (Instance) String

func (i Instance) String() string

String returns a string representation of the Instance.

Two semantically different instances may have the same string representation if the instantiated object or its type arguments shadow other types.

func (Instance) TypeParamsString

func (i Instance) TypeParamsString(open, close string) string

TypeParamsString returns part of a Go type string that represents the type parameters of the instance including the nesting type parameters, e.g. [X;Y,Z].

func (Instance) TypeString

func (i Instance) TypeString() string

TypeString returns a Go type string representing the instance (suitable for %T verb).

type InstanceMap

type InstanceMap[V any] struct {
	// contains filtered or unexported fields
}

InstanceMap implements a map-like data structure keyed by instances.

Zero value is an equivalent of an empty map. Methods are not thread-safe.

Since Instance contains a slice and is not comparable, it can not be used as a regular map key, but we can compare its fields manually. When comparing instance equality, objects are compared by pointer equality, and type arguments with types.Identical(). To reduce access complexity, we bucket entries by a combined hash of type args. This type is generally inspired by [golang.org/x/tools/go/types/typeutil#Map]

func (*InstanceMap[V]) Delete

func (im *InstanceMap[V]) Delete(key Instance) bool

Delete removes the entry with the given key, if any. It returns true if the entry was found.

func (*InstanceMap[V]) Get

func (im *InstanceMap[V]) Get(key Instance) V

Get returns the stored value for the provided key. If the key is missing from the map, zero value is returned.

func (*InstanceMap[V]) Has

func (im *InstanceMap[V]) Has(key Instance) bool

Has returns true if the given key is present in the map.

func (*InstanceMap[V]) Iterate

func (im *InstanceMap[V]) Iterate(f func(key Instance, value V))

Iterate calls function f on each entry in the map in unspecified order.

Return true from f to continue the iteration, or false to stop it.

If f should mutate the map, Iterate provides the same guarantees as Go maps: if f deletes a map entry that Iterate has not yet reached, f will not be invoked for it, but if f inserts a map entry that Iterate has not yet reached, whether or not f will be invoked for it is unspecified.

func (*InstanceMap[V]) Keys

func (im *InstanceMap[V]) Keys() []Instance

Keys returns a new slice containing the set of map keys. The order is unspecified.

func (*InstanceMap[V]) Len

func (im *InstanceMap[V]) Len() int

Len returns the number of elements in the map.

func (*InstanceMap[V]) Set

func (im *InstanceMap[V]) Set(key Instance, value V) V

Set new value for the key in the map. Returns the previous value that was stored in the map, or zero value if the key wasn't present before.

func (*InstanceMap[V]) String

func (im *InstanceMap[V]) String() string

String returns a string representation of the map's entries. The entries are sorted by string representation of the entry.

type InstanceSet

type InstanceSet struct {
	// contains filtered or unexported fields
}

InstanceSet allows collecting and processing unique Instances.

Each Instance may be added to the set any number of times, but it will be returned for processing exactly once. Processing order is not specified.

func (*InstanceSet) Add

func (iset *InstanceSet) Add(instances ...Instance) *InstanceSet

Add instances to the set. Instances that have been previously added to the set won't be requeued for processing regardless of whether they have been processed already.

func (*InstanceSet) ByObj

func (iset *InstanceSet) ByObj() map[types.Object][]Instance

ByObj returns instances grouped by object they belong to. Order is not specified.

func (*InstanceSet) ForObj

func (iset *InstanceSet) ForObj(obj types.Object) []Instance

ForObj returns the instances that belong to the given object type. Order is not specified. This returns the same values as `ByObj()[obj]`.

func (*InstanceSet) ID

func (iset *InstanceSet) ID(inst Instance) int

ID returns a unique numeric identifier assigned to an instance in the set. The ID is guaranteed to be unique among all instances of the same object within a given program. The ID will be consistent, as long as instances are added to the set in the same order.

In order to have an ID assigned, the instance must have been previously added to the set.

Note: these ids are used in the generated code as keys to the specific type/function instantiation in the type/function object. Using this has two advantages:

- More compact generated code compared to string keys derived from type args.

- Collision avoidance in case of two different types having the same name due to shadowing.

Here's an example where it's very difficult to assign non-colliding name-based keys to the two different types T:

func foo() {
    type T int
    { type T string } // Code block creates a new nested scope allowing for shadowing.
}

func (*InstanceSet) ObjHasInstances

func (iset *InstanceSet) ObjHasInstances(obj types.Object) bool

ObjHasInstances returns true if there are any instances (either trivial or non-trivial) that belong to the given object type, otherwise false.

func (*InstanceSet) Values

func (iset *InstanceSet) Values() []Instance

Values returns instances that are currently in the set. Order is not specified.

type PackageInstanceSets

type PackageInstanceSets map[string]*InstanceSet

PackageInstanceSets stores an InstanceSet for each package in a program, keyed by import path.

func (PackageInstanceSets) Add

func (i PackageInstanceSets) Add(instances ...Instance)

Add instances to the appropriate package's set. Automatically initialized new per-package sets upon a first encounter.

func (PackageInstanceSets) ID

func (i PackageInstanceSets) ID(inst Instance) int

ID returns a unique numeric identifier assigned to an instance in the set.

See: InstanceSet.ID().

func (PackageInstanceSets) Pkg

Pkg returns InstanceSet for objects defined in the given package.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver translates types defined in terms of type parameters into concrete types, given a root instance. The root instance provides context for mapping from type parameters to type arguments so that the resolver can substitute any type parameters used in types to the corresponding type arguments.

In some cases, a generic type may not be able to be fully instantiated. Generic named types that have no type arguments applied will have the type parameters substituted, however the type arguments will not be applied to instantiate the named type.

For example, given `func Foo[T any]() { type Bar[U *T] struct { x T; y U } }`, and if `Foo[int]` is used as the root for the resolver, then `Bar[U *T]` will be substituted to create the generic `Bar[U *int] struct { x int; y U }`. Alternatively, the instantiated but still generic because of the `T`, `Bar[bool] struct { x T; y bool}` will be substituted for `Foo[int]` to create the concrete `Bar[bool] struct { x int; y bool }`.

Typically the instantiated type from `info.Instances` should be substituted to resolve the implicit nesting types and create a concrete type. See internal/govendor/subst/subst.go for more details.

func NewResolver

func NewResolver(tc *types.Context, root Instance) *Resolver

NewResolver creates a new Resolver that will substitute type parameters with the type arguments as defined in the provided Instance.

func (*Resolver) Nest

func (r *Resolver) Nest() *types.Func

Nest is the nesting function that this resolver will resolve types with. This will be null if the resolver is not for a nested context,

func (*Resolver) NestTypeArgs

func (r *Resolver) NestTypeArgs() []types.Type

NestTypeArgs is the list of type arguments from the nesting function that this resolver will resolve to.

func (*Resolver) NestTypeParams

func (r *Resolver) NestTypeParams() *types.TypeParamList

NestTypeParams is the list of type parameters from the nesting function that this resolver will substitute.

func (*Resolver) String

func (r *Resolver) String() string

String gets a strings representation of the resolver for debugging.

func (*Resolver) Substitute

func (r *Resolver) Substitute(typ types.Type) types.Type

Substitute replaces references to type params in the provided type definition with the corresponding concrete types.

func (*Resolver) SubstituteAll

func (r *Resolver) SubstituteAll(list *types.TypeList) []types.Type

SubstituteAll same as Substitute, but accepts a TypeList are returns substitution results as a slice in the same order.

func (*Resolver) SubstituteSelection

func (r *Resolver) SubstituteSelection(sel typesutil.Selection) typesutil.Selection

SubstituteSelection replaces a method of field selection on a generic type defined in terms of type parameters with a method selection on a concrete instantiation of the type.

func (*Resolver) TypeArgs

func (r *Resolver) TypeArgs() []types.Type

TypeArgs is the list of type arguments that this resolver will resolve to.

func (*Resolver) TypeParams

func (r *Resolver) TypeParams() *types.TypeParamList

TypeParams is the list of type parameters that this resolver will substitute.

Jump to

Keyboard shortcuts

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