mirror of https://github.com/golang/go.git
go/types: initial steps towards customizing method signatures
Needs more work and tests. Change-Id: Ic54e5798c374254d55b46cb582d7cf87efe125d1
This commit is contained in:
parent
3663c91f3a
commit
e2ccf6356b
|
|
@ -319,7 +319,7 @@ type Func struct {
|
|||
// NewFunc returns a new function with the given signature, representing
|
||||
// the function's type.
|
||||
func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
|
||||
// don't store a nil signature
|
||||
// don't store a (typed) nil signature
|
||||
var typ Type
|
||||
if sig != nil {
|
||||
typ = sig
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ func (s *subster) typ(typ Type) (res Type) {
|
|||
return s.tuple(t)
|
||||
|
||||
case *Signature:
|
||||
recv := s.var_(t.recv) // not strictly needed (receivers cannot be parametrized)
|
||||
// TODO(gri) rethink the recv situation with respect to methods on parameterized types
|
||||
//recv := s.var_(t.recv) // not strictly needed (receivers cannot be parameterized) (?)
|
||||
recv := t.recv
|
||||
params := s.tuple(t.params)
|
||||
results := s.tuple(t.results)
|
||||
if recv != t.recv || params != t.params || results != t.results {
|
||||
|
|
@ -123,19 +125,26 @@ func (s *subster) typ(typ Type) (res Type) {
|
|||
if underlying != t.underlying {
|
||||
// create a new named type - for now use printed type in name
|
||||
// TODO(gri) consider type map to map types to indices (on the other hand, a type string seems just as good)
|
||||
if len(t.methods) > 0 {
|
||||
panic("cannot handle instantiation of types with methods yet")
|
||||
}
|
||||
// TODO(gri) review name creation and factor out
|
||||
name := TypeString(t, nil) + "<" + typeListString(s.targs) + ">"
|
||||
//s.check.dump("NAME = %s", name)
|
||||
tname, found := s.check.typMap[name]
|
||||
if !found {
|
||||
// instantiate custom methods as necessary
|
||||
var methods []*Func
|
||||
for _, m := range t.methods {
|
||||
//sig := s.typ(m.typ).(*Signature)
|
||||
sig := s.check.subst(m.typ, m.tparams, s.targs).(*Signature)
|
||||
m1 := NewFunc(m.pos, m.pkg, m.name, sig)
|
||||
//s.check.dump("%s: method %s => %s", name, m, m1)
|
||||
methods = append(methods, m1)
|
||||
}
|
||||
// TODO(gri) what is the correct position to use here?
|
||||
tname = NewTypeName(t.obj.pos, s.check.pkg, name, nil)
|
||||
//s.check.dump("name = %s", name)
|
||||
NewNamed(tname, underlying, nil) // TODO(gri) provide correct method list
|
||||
NewNamed(tname, underlying, methods)
|
||||
s.check.typMap[name] = tname
|
||||
// TODO(gri) update the method receivers?
|
||||
}
|
||||
return tname.typ
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,3 @@ func (l List(E)) First() E {
|
|||
}
|
||||
return l[0]
|
||||
}
|
||||
|
||||
// var _ string = List(string){"foo"}.First()
|
||||
|
|
@ -46,4 +46,7 @@ var (
|
|||
_ [](List(int)) = f(List(int){})
|
||||
_ List(List(int)) = [](List(int)){}
|
||||
_ = [](List(int)){}
|
||||
)
|
||||
)
|
||||
|
||||
// Parameterized types with methods
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ type Signature struct {
|
|||
// We then unpack the *Signature and use the scope for the literal body.
|
||||
scope *Scope // function scope, present for package-local signatures
|
||||
recv *Var // nil if not a method
|
||||
// TODO(gri) do we need to keep tparams in the signature?
|
||||
// TODO(gri) do we need to keep tparams in the Signature, rather than the Func object?
|
||||
// (how are they different from type parameters which we keep with the TypeName?)
|
||||
tparams []*TypeName // type parameters from left to right; or nil
|
||||
params *Tuple // (incoming) parameters from left to right; or nil
|
||||
results *Tuple // (outgoing) results from left to right; or nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue