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:
base.FatalfAt(src.NoXPos, "unhandled type: %v (%T)", typ, typ)
panic("unreachable")
}
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 {
fields := make([]*types.Field, typ.Len())
for i := range fields {
}
return fields
}
-
params := do(sig.Params())
results := do(sig.Results())
if sig.Variadic() {
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 {
}
// 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 {
case fmtTypeID, fmtTypeIDName:
if verb == 'S' {
}
b.WriteString("func")
}
+ if t.NumTParams() > 0 {
+ tconv2(b, t.TParams(), 0, mode, visited)
+ }
tconv2(b, t.Params(), 0, mode, visited)
switch t.NumResults() {
}
if funarg := t.StructType().Funarg; funarg != FunargNone {
- b.WriteByte('(')
+ open, close := '(', ')'
+ if funarg == FunargTparams {
+ open, close = '[', ']'
+ }
+ b.WriteByte(byte(open))
fieldVerb := 'v'
switch mode {
case fmtTypeID, fmtTypeIDName, fmtGo:
}
fldconv(b, f, fieldVerb, mode, visited, funarg)
}
- b.WriteByte(')')
+ b.WriteByte(byte(close))
} else {
b.WriteString("struct {")
for i, f := range t.Fields().Slice() {
case TUNSAFEPTR:
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:
b.WriteString("Txxx")
base.Warn("bad type %v %d\n", t1, w)
}
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)) {
func (t *Type) Kind() Kind { return t.kind }
// 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.
func (t *Type) Underlying() *Type { return t.underlying }
Receiver *Type // function receiver
Results *Type // function results
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
t.Extra = new(Tuple)
case TRESULTS:
t.Extra = new(Results)
+ case TTYPEPARAM:
+ t.Extra = new(Interface)
}
return t
}
}
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) Results() *Type { return t.FuncType().Results }
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) NumResults() int { return t.FuncType().Results.NumFields() }
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,
// parametes, results, and type parameters, any of which may be nil.
func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Type {
}
ft.Receiver = funargs(recvs, FunargRcvr)
- ft.Tparams = funargs(tparams, FunargTparams)
+ ft.TParams = funargs(tparams, FunargTparams)
ft.Params = funargs(params, FunargParams)
ft.Results = funargs(results, FunargResults)
ft.pkg = pkg
aType
}
+func (t *TypeParam) Obj() *TypeName {
+ return t.obj
+}
+
// NewTypeParam returns a new TypeParam.
func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
assert(bound != nil)