Involved Source Files Package typeparams contains common utilities for writing tools that
interact with generic Go code, as introduced with Go 1.18. It
supplements the standard library APIs. Notably, the StructuralTerms
API computes a minimal representation of the structural
restrictions on a type parameter.
An external version of these APIs is available in the
golang.org/x/exp/typeparams module.coretype.gofree.gonormalize.gotermlist.gotypeterm.go
Package-Level Type Names (total 4, in which 1 is exported)
/* sort exporteds by: | */
Free is a memoization of the set of free type parameters within a
type. It makes a sequence of calls to [Free.Has] for overlapping
types more efficient. The zero value is ready for use.
NOTE: Adapted from go/types/infer.go. If it is later exported, factor.seenmap[types.Type]bool Has reports whether the specified type has a free type parameter.
A termSet holds the normalized set of terms for a given type.
The name termSet is intentionally distinct from 'type set': a type set is
all types that implement a type (and includes method restrictions), whereas
a term set just represents the structural restrictions on a type.completebooltermstermlist
func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error)
func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error)
Package-Level Functions (total 14, in which 10 are exported)
CoreType returns the core type of T or nil if T does not have a core type.
See https://go.dev/ref/spec#Core_types for the definition of a core type.
Deref returns the type of the variable pointed to by t,
if t's core type is a pointer; otherwise it returns t.
Do not assume that Deref(T)==T implies T is not a pointer:
consider "type T *T", for example.
TODO(adonovan): ideally this would live in typesinternal, but that
creates an import cycle. Move there when we melt this package down.
InterfaceTermSet computes the normalized terms for a constraint interface,
returning an error if the term set cannot be computed or is empty. In the
latter case, the error will be ErrEmptyTypeSet.
See the documentation of StructuralTerms for more information on
normalization.
IsTypeParam reports whether t is a type parameter (or an alias of one).
MustDeref returns the type of the variable pointed to by t.
It panics if t's core type is not a pointer.
TODO(adonovan): ideally this would live in typesinternal, but that
creates an import cycle. Move there when we melt this package down.
NormalTerms returns a slice of terms representing the normalized structural
type restrictions of a type, if any.
For all types other than *types.TypeParam, *types.Interface, and
*types.Union, this is just a single term with Tilde() == false and
Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see
below.
Structural type restrictions of a type parameter are created via
non-interface types embedded in its constraint interface (directly, or via a
chain of interface embeddings). For example, in the declaration type
T[P interface{~int; m()}] int the structural restriction of the type
parameter P is ~int.
With interface embedding and unions, the specification of structural type
restrictions may be arbitrarily complex. For example, consider the
following:
type A interface{ ~string|~[]byte }
type B interface{ int|string }
type C interface { ~string|~int }
type T[P interface{ A|B; C }] int
In this example, the structural type restriction of P is ~string|int: A|B
expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
which when intersected with C (~string|~int) yields ~string|int.
NormalTerms computes these expansions and reductions, producing a
"normalized" form of the embeddings. A structural restriction is normalized
if it is a single union containing no interface terms, and is minimal in the
sense that removing any term changes the set of types satisfying the
constraint. It is left as a proof for the reader that, modulo sorting, there
is exactly one such normalized form.
Because the minimal representation always takes this form, NormalTerms
returns a slice of tilde terms corresponding to the terms of the union in
the normalized structural restriction. An error is returned if the type is
invalid, exceeds complexity bounds, or has an empty type set. In the latter
case, NormalTerms returns ErrEmptyTypeSet.
NormalTerms makes no guarantees about the order of terms, except that it
is deterministic.
PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
will panic.
StructuralTerms returns a slice of terms representing the normalized
structural type restrictions of a type parameter, if any.
Structural type restrictions of a type parameter are created via
non-interface types embedded in its constraint interface (directly, or via a
chain of interface embeddings). For example, in the declaration
type T[P interface{~int; m()}] int
the structural restriction of the type parameter P is ~int.
With interface embedding and unions, the specification of structural type
restrictions may be arbitrarily complex. For example, consider the
following:
type A interface{ ~string|~[]byte }
type B interface{ int|string }
type C interface { ~string|~int }
type T[P interface{ A|B; C }] int
In this example, the structural type restriction of P is ~string|int: A|B
expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
which when intersected with C (~string|~int) yields ~string|int.
StructuralTerms computes these expansions and reductions, producing a
"normalized" form of the embeddings. A structural restriction is normalized
if it is a single union containing no interface terms, and is minimal in the
sense that removing any term changes the set of types satisfying the
constraint. It is left as a proof for the reader that, modulo sorting, there
is exactly one such normalized form.
Because the minimal representation always takes this form, StructuralTerms
returns a slice of tilde terms corresponding to the terms of the union in
the normalized structural restriction. An error is returned if the
constraint interface is invalid, exceeds complexity bounds, or has an empty
type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.
StructuralTerms makes no guarantees about the order of terms, except that it
is deterministic.
UnionTermSet computes the normalized terms for a union, returning an error
if the term set cannot be computed or is empty. In the latter case, the
error will be ErrEmptyTypeSet.
See the documentation of StructuralTerms for more information on
normalization.
UnpackIndexExpr extracts data from AST nodes that represent index
expressions.
For an ast.IndexExpr, the resulting indices slice will contain exactly one
index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
number of index expressions.
For nodes that don't represent index expressions, the first return value of
UnpackIndexExpr will be nil.