Skip to content

go/types: NewType{Param,}List #79603

@mrkfrmn

Description

@mrkfrmn

Proposal Details

The go/types API exposes type parameters as a *TypeParamList. There is no exported mechanism to modify a TypeParamList. With generic methods, we sometimes want to view the receiver and method type parameters as a single type parameter list.

Motivation

One use case is in the noder, which merges receiver and method type arguments into a single set of explicit type arguments. It must first convert each list to a slice:

// asTypeParamSlice unpacks a types2.TypeParamList to a []types2.TypeParam
func asTypeParamSlice(l *types2.TypeParamList) []*types2.TypeParam {
	if l.Len() == 0 {
		return nil
	}
	s := make([]*types2.TypeParam, l.Len())
	for i := range l.Len() {
		s[i] = l.At(i)
	}
	return s
}

If the noder could create new type parameter lists, it wouldn't need to swap for a []*TypeParam.

Another example is go/ssa in x/tools. There, Function.TypeParams returns a TypeParamList. With generic methods, to uphold this API, we have to resort to an unsafe cast relying on the layout of TypeParamList:

func consTypeParamLists(l, r *types.TypeParamList) *types.TypeParamList {
	tpars := make([]*types.TypeParam, l.Len()+r.Len())
	for i := range l.Len() {
		tpars[i] = l.At(i)
	}
	for i := range r.Len() {
		tpars[i+l.Len()] = r.At(i)
	}
	return (*types.TypeParamList)(unsafe.Pointer(&tpars))

This isn't ideal. Note that the Function.TypeParams method will be deprecated in favor of methods which return either the receiver or method type parameters—not both.

Supposed API

I think all we need is a constructor, which is quite basic:

func NewTypeParamList(tparams ...*TypeParam) *TypeParamList {
    return &TypeParamList{ tparams: tparams }
}

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

Status
Accepted

Relationships

None yet

Development

No branches or pull requests

Issue actions