// 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. func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) { … } // PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on // the cardinality of indices. Calling PackIndexExpr with len(indices) == 0 // will panic. func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { … } // IsTypeParam reports whether t is a type parameter (or an alias of one). func IsTypeParam(t types.Type) bool { … } // GenericAssignableTo is a generalization of types.AssignableTo that // implements the following rule for uninstantiated generic types: // // If V and T are generic named types, then V is considered assignable to T if, // for every possible instantiation of V[A_1, ..., A_N], the instantiation // T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N]. // // If T has structural constraints, they must be satisfied by V. // // For example, consider the following type declarations: // // type Interface[T any] interface { // Accept(T) // } // // type Container[T any] struct { // Element T // } // // func (c Container[T]) Accept(t T) { c.Element = t } // // In this case, GenericAssignableTo reports that instantiations of Container // are assignable to the corresponding instantiation of Interface. func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { … }