1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build go1.18
6// +build go1.18
7
8package typeparams
9
10import (
11	"go/ast"
12	"go/token"
13	"go/types"
14)
15
16// GetIndexExprData extracts data from AST nodes that represent index
17// expressions.
18//
19// For an ast.IndexExpr, the resulting IndexExprData will have exactly one
20// index expression. For an ast.IndexListExpr (go1.18+), it may have a
21// variable number of index expressions.
22//
23// For nodes that don't represent index expressions, GetIndexExprData returns
24// nil.
25// TODO(rfindley): remove this function in favor of using the alias below.
26func GetIndexExprData(n ast.Node) *IndexExprData {
27	switch e := n.(type) {
28	case *ast.IndexExpr:
29		return &IndexExprData{
30			X:       e.X,
31			Lbrack:  e.Lbrack,
32			Indices: []ast.Expr{e.Index},
33			Rbrack:  e.Rbrack,
34		}
35	case *ast.IndexListExpr:
36		return (*IndexExprData)(e)
37	}
38	return nil
39}
40
41// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
42// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
43// will panic.
44func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
45	switch len(indices) {
46	case 0:
47		panic("empty indices")
48	case 1:
49		return &ast.IndexExpr{
50			X:      x,
51			Lbrack: lbrack,
52			Index:  indices[0],
53			Rbrack: rbrack,
54		}
55	default:
56		return &ast.IndexListExpr{
57			X:       x,
58			Lbrack:  lbrack,
59			Indices: indices,
60			Rbrack:  rbrack,
61		}
62	}
63}
64
65// IndexListExpr is an alias for ast.IndexListExpr.
66type IndexListExpr = ast.IndexListExpr
67
68// ForTypeSpec returns n.TypeParams.
69func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList {
70	if n == nil {
71		return nil
72	}
73	return n.TypeParams
74}
75
76// ForFuncType returns n.TypeParams.
77func ForFuncType(n *ast.FuncType) *ast.FieldList {
78	if n == nil {
79		return nil
80	}
81	return n.TypeParams
82}
83
84// TypeParam is an alias for types.TypeParam
85type TypeParam = types.TypeParam
86
87// TypeParamList is an alias for types.TypeParamList
88type TypeParamList = types.TypeParamList
89
90// TypeList is an alias for types.TypeList
91type TypeList = types.TypeList
92
93// NewTypeParam calls types.NewTypeParam.
94func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
95	return types.NewTypeParam(name, constraint)
96}
97
98// SetTypeParamConstraint calls tparam.SetConstraint(constraint).
99func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
100	tparam.SetConstraint(constraint)
101}
102
103// NewSignatureType calls types.NewSignatureType.
104func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
105	return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic)
106}
107
108// ForSignature returns sig.TypeParams()
109func ForSignature(sig *types.Signature) *TypeParamList {
110	return sig.TypeParams()
111}
112
113// RecvTypeParams returns sig.RecvTypeParams().
114func RecvTypeParams(sig *types.Signature) *TypeParamList {
115	return sig.RecvTypeParams()
116}
117
118// IsComparable calls iface.IsComparable().
119func IsComparable(iface *types.Interface) bool {
120	return iface.IsComparable()
121}
122
123// IsMethodSet calls iface.IsMethodSet().
124func IsMethodSet(iface *types.Interface) bool {
125	return iface.IsMethodSet()
126}
127
128// IsImplicit calls iface.IsImplicit().
129func IsImplicit(iface *types.Interface) bool {
130	return iface.IsImplicit()
131}
132
133// MarkImplicit calls iface.MarkImplicit().
134func MarkImplicit(iface *types.Interface) {
135	iface.MarkImplicit()
136}
137
138// ForNamed extracts the (possibly empty) type parameter object list from
139// named.
140func ForNamed(named *types.Named) *TypeParamList {
141	return named.TypeParams()
142}
143
144// SetForNamed sets the type params tparams on n. Each tparam must be of
145// dynamic type *types.TypeParam.
146func SetForNamed(n *types.Named, tparams []*TypeParam) {
147	n.SetTypeParams(tparams)
148}
149
150// NamedTypeArgs returns named.TypeArgs().
151func NamedTypeArgs(named *types.Named) *TypeList {
152	return named.TypeArgs()
153}
154
155// NamedTypeOrigin returns named.Orig().
156func NamedTypeOrigin(named *types.Named) types.Type {
157	return named.Origin()
158}
159
160// Term is an alias for types.Term.
161type Term = types.Term
162
163// NewTerm calls types.NewTerm.
164func NewTerm(tilde bool, typ types.Type) *Term {
165	return types.NewTerm(tilde, typ)
166}
167
168// Union is an alias for types.Union
169type Union = types.Union
170
171// NewUnion calls types.NewUnion.
172func NewUnion(terms []*Term) *Union {
173	return types.NewUnion(terms)
174}
175
176// InitInstanceInfo initializes info to record information about type and
177// function instances.
178func InitInstanceInfo(info *types.Info) {
179	info.Instances = make(map[*ast.Ident]types.Instance)
180}
181
182// Instance is an alias for types.Instance.
183type Instance = types.Instance
184
185// GetInstances returns info.Instances.
186func GetInstances(info *types.Info) map[*ast.Ident]Instance {
187	return info.Instances
188}
189
190// Context is an alias for types.Context.
191type Context = types.Context
192
193// Instantiate calls types.Instantiate.
194func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
195	return types.Instantiate(ctxt, typ, targs, validate)
196}
197