mirror of
https://github.com/golang/go
synced 2024-11-26 12:58:06 -07:00
[dev.typeparams] cmd/compile: start translating type params in noder2
Also, make some fmt changes so that the type parameters and the typeparam type are displayed in -W=2. You can now parse a simple generic function (but not generic calls or generic types) and print out the noder IR via 'go tool compile -G=2 -W=2 func.go' Change-Id: I1f070fc4a96174a447763ad37999e61c25905901 Reviewed-on: https://go-review.googlesource.com/c/go/+/287833 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
a59cb5109d
commit
0aafd69124
@ -100,6 +100,12 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
|
|||||||
|
|
||||||
return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...))
|
return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...))
|
||||||
|
|
||||||
|
case *types2.TypeParam:
|
||||||
|
tp := types.NewTypeParam(g.tpkg(typ), g.typ(typ.Bound()))
|
||||||
|
// Save the name of the type parameter in the sym of the type.
|
||||||
|
tp.SetSym(g.sym(typ.Obj()))
|
||||||
|
return tp
|
||||||
|
|
||||||
default:
|
default:
|
||||||
base.FatalfAt(src.NoXPos, "unhandled type: %v (%T)", typ, typ)
|
base.FatalfAt(src.NoXPos, "unhandled type: %v (%T)", typ, typ)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
@ -107,6 +113,13 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type {
|
func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type {
|
||||||
|
tparams2 := sig.TParams()
|
||||||
|
tparams := make([]*types.Field, len(tparams2))
|
||||||
|
for i := range tparams {
|
||||||
|
tp := tparams2[i]
|
||||||
|
tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ(tp.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
do := func(typ *types2.Tuple) []*types.Field {
|
do := func(typ *types2.Tuple) []*types.Field {
|
||||||
fields := make([]*types.Field, typ.Len())
|
fields := make([]*types.Field, typ.Len())
|
||||||
for i := range fields {
|
for i := range fields {
|
||||||
@ -114,14 +127,13 @@ func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type
|
|||||||
}
|
}
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
params := do(sig.Params())
|
params := do(sig.Params())
|
||||||
results := do(sig.Results())
|
results := do(sig.Results())
|
||||||
if sig.Variadic() {
|
if sig.Variadic() {
|
||||||
params[len(params)-1].SetIsDDD(true)
|
params[len(params)-1].SetIsDDD(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.NewSignature(g.tpkg(sig), recv, nil, params, results)
|
return types.NewSignature(g.tpkg(sig), recv, tparams, params, results)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *irgen) param(v *types2.Var) *types.Field {
|
func (g *irgen) param(v *types2.Var) *types.Field {
|
||||||
|
@ -318,7 +318,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unless the 'L' flag was specified, if the type has a name, just print that name.
|
// Unless the 'L' flag was specified, if the type has a name, just print that name.
|
||||||
if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] {
|
if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] && t.Kind() != TTYPEPARAM {
|
||||||
switch mode {
|
switch mode {
|
||||||
case fmtTypeID, fmtTypeIDName:
|
case fmtTypeID, fmtTypeIDName:
|
||||||
if verb == 'S' {
|
if verb == 'S' {
|
||||||
@ -478,6 +478,9 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
|||||||
}
|
}
|
||||||
b.WriteString("func")
|
b.WriteString("func")
|
||||||
}
|
}
|
||||||
|
if t.NumTParams() > 0 {
|
||||||
|
tconv2(b, t.TParams(), 0, mode, visited)
|
||||||
|
}
|
||||||
tconv2(b, t.Params(), 0, mode, visited)
|
tconv2(b, t.Params(), 0, mode, visited)
|
||||||
|
|
||||||
switch t.NumResults() {
|
switch t.NumResults() {
|
||||||
@ -515,7 +518,11 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
|||||||
}
|
}
|
||||||
|
|
||||||
if funarg := t.StructType().Funarg; funarg != FunargNone {
|
if funarg := t.StructType().Funarg; funarg != FunargNone {
|
||||||
b.WriteByte('(')
|
open, close := '(', ')'
|
||||||
|
if funarg == FunargTparams {
|
||||||
|
open, close = '[', ']'
|
||||||
|
}
|
||||||
|
b.WriteByte(byte(open))
|
||||||
fieldVerb := 'v'
|
fieldVerb := 'v'
|
||||||
switch mode {
|
switch mode {
|
||||||
case fmtTypeID, fmtTypeIDName, fmtGo:
|
case fmtTypeID, fmtTypeIDName, fmtGo:
|
||||||
@ -528,7 +535,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
|||||||
}
|
}
|
||||||
fldconv(b, f, fieldVerb, mode, visited, funarg)
|
fldconv(b, f, fieldVerb, mode, visited, funarg)
|
||||||
}
|
}
|
||||||
b.WriteByte(')')
|
b.WriteByte(byte(close))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString("struct {")
|
b.WriteString("struct {")
|
||||||
for i, f := range t.Fields().Slice() {
|
for i, f := range t.Fields().Slice() {
|
||||||
@ -554,6 +561,15 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
|||||||
case TUNSAFEPTR:
|
case TUNSAFEPTR:
|
||||||
b.WriteString("unsafe.Pointer")
|
b.WriteString("unsafe.Pointer")
|
||||||
|
|
||||||
|
case TTYPEPARAM:
|
||||||
|
if t.Sym() != nil {
|
||||||
|
sconv2(b, t.Sym(), 'v', mode)
|
||||||
|
} else {
|
||||||
|
b.WriteString("tp")
|
||||||
|
// Print out the pointer value for now to disambiguate type params
|
||||||
|
b.WriteString(fmt.Sprintf("%p", t))
|
||||||
|
}
|
||||||
|
|
||||||
case Txxx:
|
case Txxx:
|
||||||
b.WriteString("Txxx")
|
b.WriteString("Txxx")
|
||||||
|
|
||||||
|
@ -499,6 +499,11 @@ func CalcSize(t *Type) {
|
|||||||
base.Warn("bad type %v %d\n", t1, w)
|
base.Warn("bad type %v %d\n", t1, w)
|
||||||
}
|
}
|
||||||
t.Align = 1
|
t.Align = 1
|
||||||
|
|
||||||
|
case TTYPEPARAM:
|
||||||
|
// TODO(danscales) - remove when we eliminate the need
|
||||||
|
// to do CalcSize in noder2 (which shouldn't be needed in the noder)
|
||||||
|
w = int64(PtrSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if PtrSize == 4 && w != int64(int32(w)) {
|
if PtrSize == 4 && w != int64(int32(w)) {
|
||||||
|
@ -204,7 +204,8 @@ func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
|
|||||||
func (t *Type) Kind() Kind { return t.kind }
|
func (t *Type) Kind() Kind { return t.kind }
|
||||||
|
|
||||||
// Sym returns the name of type t.
|
// Sym returns the name of type t.
|
||||||
func (t *Type) Sym() *Sym { return t.sym }
|
func (t *Type) Sym() *Sym { return t.sym }
|
||||||
|
func (t *Type) SetSym(sym *Sym) { t.sym = sym }
|
||||||
|
|
||||||
// Underlying returns the underlying type of type t.
|
// Underlying returns the underlying type of type t.
|
||||||
func (t *Type) Underlying() *Type { return t.underlying }
|
func (t *Type) Underlying() *Type { return t.underlying }
|
||||||
@ -285,7 +286,7 @@ type Func struct {
|
|||||||
Receiver *Type // function receiver
|
Receiver *Type // function receiver
|
||||||
Results *Type // function results
|
Results *Type // function results
|
||||||
Params *Type // function params
|
Params *Type // function params
|
||||||
Tparams *Type // type params of receiver (if method) or function
|
TParams *Type // type params of receiver (if method) or function
|
||||||
|
|
||||||
pkg *Pkg
|
pkg *Pkg
|
||||||
|
|
||||||
@ -512,6 +513,8 @@ func New(et Kind) *Type {
|
|||||||
t.Extra = new(Tuple)
|
t.Extra = new(Tuple)
|
||||||
case TRESULTS:
|
case TRESULTS:
|
||||||
t.Extra = new(Results)
|
t.Extra = new(Results)
|
||||||
|
case TTYPEPARAM:
|
||||||
|
t.Extra = new(Interface)
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
@ -769,10 +772,12 @@ func (t *Type) wantEtype(et Kind) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Recvs() *Type { return t.FuncType().Receiver }
|
func (t *Type) Recvs() *Type { return t.FuncType().Receiver }
|
||||||
|
func (t *Type) TParams() *Type { return t.FuncType().TParams }
|
||||||
func (t *Type) Params() *Type { return t.FuncType().Params }
|
func (t *Type) Params() *Type { return t.FuncType().Params }
|
||||||
func (t *Type) Results() *Type { return t.FuncType().Results }
|
func (t *Type) Results() *Type { return t.FuncType().Results }
|
||||||
|
|
||||||
func (t *Type) NumRecvs() int { return t.FuncType().Receiver.NumFields() }
|
func (t *Type) NumRecvs() int { return t.FuncType().Receiver.NumFields() }
|
||||||
|
func (t *Type) NumTParams() int { return t.FuncType().TParams.NumFields() }
|
||||||
func (t *Type) NumParams() int { return t.FuncType().Params.NumFields() }
|
func (t *Type) NumParams() int { return t.FuncType().Params.NumFields() }
|
||||||
func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }
|
func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }
|
||||||
|
|
||||||
@ -1648,6 +1653,15 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTypeParam returns a new type param with the given constraint (which may
|
||||||
|
// not really be needed except for the type checker).
|
||||||
|
func NewTypeParam(pkg *Pkg, constraint *Type) *Type {
|
||||||
|
t := New(TTYPEPARAM)
|
||||||
|
t.methods = constraint.methods
|
||||||
|
t.Extra.(*Interface).pkg = pkg
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
// NewSignature returns a new function type for the given receiver,
|
// NewSignature returns a new function type for the given receiver,
|
||||||
// parametes, results, and type parameters, any of which may be nil.
|
// parametes, results, and type parameters, any of which may be nil.
|
||||||
func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Type {
|
func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Type {
|
||||||
@ -1669,7 +1683,7 @@ func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
ft.Receiver = funargs(recvs, FunargRcvr)
|
ft.Receiver = funargs(recvs, FunargRcvr)
|
||||||
ft.Tparams = funargs(tparams, FunargTparams)
|
ft.TParams = funargs(tparams, FunargTparams)
|
||||||
ft.Params = funargs(params, FunargParams)
|
ft.Params = funargs(params, FunargParams)
|
||||||
ft.Results = funargs(results, FunargResults)
|
ft.Results = funargs(results, FunargResults)
|
||||||
ft.pkg = pkg
|
ft.pkg = pkg
|
||||||
|
@ -837,6 +837,10 @@ type TypeParam struct {
|
|||||||
aType
|
aType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TypeParam) Obj() *TypeName {
|
||||||
|
return t.obj
|
||||||
|
}
|
||||||
|
|
||||||
// NewTypeParam returns a new TypeParam.
|
// NewTypeParam returns a new TypeParam.
|
||||||
func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
|
func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
|
||||||
assert(bound != nil)
|
assert(bound != nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user