go/types: fix a bug with type instantiation

Change-Id: I977bb5525a40d0e17c27bbc01d7c77426e1bad00
This commit is contained in:
Robert Griesemer 2019-08-16 14:41:59 -07:00
parent e73de77f33
commit 1f06612063
3 changed files with 55 additions and 13 deletions

View File

@ -122,22 +122,25 @@ func (s *subster) typ(typ Type) (res Type) {
}
case *Named:
// if not all type parameters are known, create a parameterized type
if isParameterizedList(s.targs) {
return &Parameterized{t.obj, s.targs}
}
// TODO(gri) revisit name creation (function local types, etc.) and factor out
name := TypeString(t, nil) + "<" + typeListString(s.targs) + ">"
//s.check.dump("- %s => %s", t, name)
if tname, found := s.check.typMap[name]; found {
//s.check.dump("- found %s", tname)
return tname.typ
}
// create a new named type and populate caches to avoid endless recursion
// TODO(gri) should use actual instantiation position
tname := NewTypeName(t.obj.pos, s.check.pkg, name, nil)
s.check.typMap[name] = tname
named := NewNamed(tname, nil, nil)
s.cache[t] = named
//s.check.dump("- installed %s", tname)
named.underlying = s.typ(t.underlying).Underlying()
//s.check.dump("- finished %s", tname)
// instantiate custom methods as necessary
for _, m := range t.methods {
// methods may not have a fully set up signature yet

View File

@ -1,13 +1,30 @@
// Copyright 2019 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 p
type S(type T) struct {
f T
type Pair(type K) struct {
key K
}
func (r S(T)) m() T {
return r.f
}
type Receiver(type T) struct {
values T
}
type Iterator(type K) struct {
r Receiver(Pair(K))
}
func (r Receiver(T)) Values() T {
return r.values
}
func Values (type T) (r Receiver(T)) T {
return r.values
}
func (it Iterator(K)) Next() K {
// x := it.r.Values()
x := Values(Pair(K))(it.r)
// it : Iterator(K)
// it.r : Receiver(Pair(K))
// it.r.Values: Pair(K)
return x.key
}

View File

@ -56,3 +56,25 @@ func (l List(E)) Head() (_ E, _ bool) {
}
return
}
// A test case for instantiating types with other types (extracted from map.go2)
type Pair(type K) struct {
key K
}
type Receiver(type T) struct {
values T
}
type Iterator(type K) struct {
r Receiver(Pair(K))
}
func Values (type T) (r Receiver(T)) T {
return r.values
}
func (it Iterator(K)) Next() K {
return Values(Pair(K))(it.r).key
}