mirror of https://github.com/golang/go.git
cmd/api: support type parameters
Fixes #48706 Change-Id: If0f8d0b49300027e3b2b46f6870302acf2e00f4e Reviewed-on: https://go-review.googlesource.com/c/go/+/354612 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
d90f0b9200
commit
6372e7efba
|
|
@ -706,6 +706,36 @@ func sortedMethodNames(typ *types.Interface) []string {
|
|||
return list
|
||||
}
|
||||
|
||||
// sortedEmbeddeds returns constraint types embedded in an
|
||||
// interface. It does not include embedded interface types or methods.
|
||||
func (w *Walker) sortedEmbeddeds(typ *types.Interface) []string {
|
||||
n := typ.NumEmbeddeds()
|
||||
list := make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
emb := typ.EmbeddedType(i)
|
||||
switch emb := emb.(type) {
|
||||
case *types.Interface:
|
||||
list = append(list, w.sortedEmbeddeds(emb)...)
|
||||
case *types.Union:
|
||||
var buf bytes.Buffer
|
||||
nu := emb.Len()
|
||||
for i := 0; i < nu; i++ {
|
||||
if i > 0 {
|
||||
buf.WriteString(" | ")
|
||||
}
|
||||
term := emb.Term(i)
|
||||
if term.Tilde() {
|
||||
buf.WriteByte('~')
|
||||
}
|
||||
w.writeType(&buf, term.Type())
|
||||
}
|
||||
list = append(list, buf.String())
|
||||
}
|
||||
}
|
||||
sort.Strings(list)
|
||||
return list
|
||||
}
|
||||
|
||||
func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) {
|
||||
switch typ := typ.(type) {
|
||||
case *types.Basic:
|
||||
|
|
@ -763,9 +793,16 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) {
|
|||
|
||||
case *types.Interface:
|
||||
buf.WriteString("interface{")
|
||||
if typ.NumMethods() > 0 {
|
||||
if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 {
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
if typ.NumMethods() > 0 {
|
||||
buf.WriteString(strings.Join(sortedMethodNames(typ), ", "))
|
||||
}
|
||||
if typ.NumEmbeddeds() > 0 {
|
||||
buf.WriteString(strings.Join(w.sortedEmbeddeds(typ), ", "))
|
||||
}
|
||||
if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 {
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
buf.WriteString("}")
|
||||
|
|
@ -800,12 +837,18 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) {
|
|||
}
|
||||
buf.WriteString(typ.Obj().Name())
|
||||
|
||||
case *types.TypeParam:
|
||||
buf.WriteString(typ.Obj().Name())
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown type %T", typ))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) {
|
||||
if tparams := sig.TypeParams(); tparams != nil {
|
||||
w.writeTypeParams(buf, tparams, true)
|
||||
}
|
||||
w.writeParams(buf, sig.Params(), sig.Variadic())
|
||||
switch res := sig.Results(); res.Len() {
|
||||
case 0:
|
||||
|
|
@ -819,6 +862,23 @@ func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *Walker) writeTypeParams(buf *bytes.Buffer, tparams *types.TypeParamList, withConstraints bool) {
|
||||
buf.WriteByte('[')
|
||||
c := tparams.Len()
|
||||
for i := 0; i < c; i++ {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
tp := tparams.At(i)
|
||||
buf.WriteString(tp.Obj().Name())
|
||||
if withConstraints {
|
||||
buf.WriteByte(' ')
|
||||
w.writeType(buf, tp.Constraint())
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
}
|
||||
|
||||
func (w *Walker) writeParams(buf *bytes.Buffer, t *types.Tuple, variadic bool) {
|
||||
buf.WriteByte('(')
|
||||
for i, n := 0, t.Len(); i < n; i++ {
|
||||
|
|
@ -872,6 +932,12 @@ func (w *Walker) emitObj(obj types.Object) {
|
|||
|
||||
func (w *Walker) emitType(obj *types.TypeName) {
|
||||
name := obj.Name()
|
||||
if tparams := obj.Type().(*types.Named).TypeParams(); tparams != nil {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(name)
|
||||
w.writeTypeParams(&buf, tparams, true)
|
||||
name = buf.String()
|
||||
}
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
|
|
@ -995,7 +1061,13 @@ func (w *Walker) emitMethod(m *types.Selection) {
|
|||
log.Fatalf("exported method with unexported receiver base type: %s", m)
|
||||
}
|
||||
}
|
||||
w.emitf("method (%s) %s%s", w.typeString(recv), m.Obj().Name(), w.signatureString(sig))
|
||||
tps := ""
|
||||
if rtp := sig.RecvTypeParams(); rtp != nil {
|
||||
var buf bytes.Buffer
|
||||
w.writeTypeParams(&buf, rtp, false)
|
||||
tps = buf.String()
|
||||
}
|
||||
w.emitf("method (%s%s) %s%s", w.typeString(recv), tps, m.Obj().Name(), w.signatureString(sig))
|
||||
}
|
||||
|
||||
func (w *Walker) emitf(format string, args ...interface{}) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
pkg p4, func NewPair[T1 interface{ M }, T2 interface{ ~int }](T1, T2) Pair
|
||||
pkg p4, method (Pair[_, X2]) Second() X2
|
||||
pkg p4, method (Pair[X1, _]) First() X1
|
||||
pkg p4, type Pair[T1 interface{ M }, T2 interface{ ~int }] struct
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p4
|
||||
|
||||
type Pair[T1 interface { M() }, T2 ~int] struct {
|
||||
f1 T1
|
||||
f2 T2
|
||||
}
|
||||
|
||||
func NewPair[T1 interface { M() }, T2 ~int](v1 T1, v2 T2) Pair[T1, T2] {
|
||||
return Pair[T1, T2]{f1: v1, f2: v2}
|
||||
}
|
||||
|
||||
func (p Pair[X1, _]) First() X1 {
|
||||
return p.f1
|
||||
}
|
||||
|
||||
func (p Pair[_, X2]) Second() X2 {
|
||||
return p.f2
|
||||
}
|
||||
Loading…
Reference in New Issue