mirror of
https://github.com/golang/go
synced 2024-11-26 13:08:08 -07:00
go/types: use []*TypeParam rather than []*TypeName type param lists
Making this change improves type safety slightly, and avoids many internal type assertions. Change-Id: I26519b0e57068e944e8243983ae90553d79e59c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/343932 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
9fe5c7f122
commit
2438660602
@ -632,7 +632,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList {
|
func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList {
|
||||||
var tparams []*TypeName
|
var tparams []*TypeParam
|
||||||
// Declare type parameters up-front, with empty interface as type bound.
|
// Declare type parameters up-front, with empty interface as type bound.
|
||||||
// The scope of type parameters starts at the beginning of the type parameter
|
// The scope of type parameters starts at the beginning of the type parameter
|
||||||
// list (so we can have mutually recursive parameterized interfaces).
|
// list (so we can have mutually recursive parameterized interfaces).
|
||||||
@ -648,7 +648,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList {
|
|||||||
}
|
}
|
||||||
bound = check.boundType(f.Type)
|
bound = check.boundType(f.Type)
|
||||||
for i := range f.Names {
|
for i := range f.Names {
|
||||||
tparams[index+i].typ.(*TypeParam).bound = bound
|
tparams[index+i].bound = bound
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
@ -658,11 +658,11 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList {
|
|||||||
return bindTParams(tparams)
|
return bindTParams(tparams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName {
|
func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
|
tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
|
||||||
check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect
|
tpar := check.NewTypeParam(tname, &emptyInterface) // assigns type to tpar as a side-effect
|
||||||
check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position
|
check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position
|
||||||
tparams = append(tparams, tpar)
|
tparams = append(tparams, tpar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Constraint type inference is used after each step to expand the set of type arguments.
|
// Constraint type inference is used after each step to expand the set of type arguments.
|
||||||
//
|
//
|
||||||
func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) {
|
func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) {
|
||||||
if debug {
|
if debug {
|
||||||
defer func() {
|
defer func() {
|
||||||
assert(result == nil || len(result) == len(tparams))
|
assert(result == nil || len(result) == len(tparams))
|
||||||
@ -121,7 +121,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allFailed {
|
if allFailed {
|
||||||
check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams))
|
check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,23 +218,23 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type,
|
|||||||
assert(index >= 0 && targs[index] == nil)
|
assert(index >= 0 && targs[index] == nil)
|
||||||
tpar := tparams[index]
|
tpar := tparams[index]
|
||||||
if report {
|
if report {
|
||||||
check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.name, tpar.pos, targs)
|
check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeNamesString produces a string containing all the
|
// typeParamsString produces a string containing all the type parameter names
|
||||||
// type names in list suitable for human consumption.
|
// in list suitable for human consumption.
|
||||||
func typeNamesString(list []*TypeName) string {
|
func typeParamsString(list []*TypeParam) string {
|
||||||
// common cases
|
// common cases
|
||||||
n := len(list)
|
n := len(list)
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
return ""
|
return ""
|
||||||
case 1:
|
case 1:
|
||||||
return list[0].name
|
return list[0].obj.name
|
||||||
case 2:
|
case 2:
|
||||||
return list[0].name + " and " + list[1].name
|
return list[0].obj.name + " and " + list[1].obj.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// general case (n > 2)
|
// general case (n > 2)
|
||||||
@ -243,15 +243,15 @@ func typeNamesString(list []*TypeName) string {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
b.WriteString(", ")
|
b.WriteString(", ")
|
||||||
}
|
}
|
||||||
b.WriteString(tname.name)
|
b.WriteString(tname.obj.name)
|
||||||
}
|
}
|
||||||
b.WriteString(", and ")
|
b.WriteString(", and ")
|
||||||
b.WriteString(list[n-1].name)
|
b.WriteString(list[n-1].obj.name)
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsParameterized reports whether typ contains any of the type parameters of tparams.
|
// IsParameterized reports whether typ contains any of the type parameters of tparams.
|
||||||
func isParameterized(tparams []*TypeName, typ Type) bool {
|
func isParameterized(tparams []*TypeParam, typ Type) bool {
|
||||||
w := tpWalker{
|
w := tpWalker{
|
||||||
seen: make(map[Type]bool),
|
seen: make(map[Type]bool),
|
||||||
tparams: tparams,
|
tparams: tparams,
|
||||||
@ -261,7 +261,7 @@ func isParameterized(tparams []*TypeName, typ Type) bool {
|
|||||||
|
|
||||||
type tpWalker struct {
|
type tpWalker struct {
|
||||||
seen map[Type]bool
|
seen map[Type]bool
|
||||||
tparams []*TypeName
|
tparams []*TypeParam
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tpWalker) isParameterized(typ Type) (res bool) {
|
func (w *tpWalker) isParameterized(typ Type) (res bool) {
|
||||||
@ -334,7 +334,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
|
|||||||
|
|
||||||
case *TypeParam:
|
case *TypeParam:
|
||||||
// t must be one of w.tparams
|
// t must be one of w.tparams
|
||||||
return t.index < len(w.tparams) && w.tparams[t.index].typ == t
|
return t.index < len(w.tparams) && w.tparams[t.index] == t
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unreachable()
|
unreachable()
|
||||||
@ -360,7 +360,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool {
|
|||||||
// first type argument in that list that couldn't be inferred (and thus is nil). If all
|
// first type argument in that list that couldn't be inferred (and thus is nil). If all
|
||||||
// type arguments were inferred successfully, index is < 0. The number of type arguments
|
// type arguments were inferred successfully, index is < 0. The number of type arguments
|
||||||
// provided may be less than the number of type parameters, but there must be at least one.
|
// provided may be less than the number of type parameters, but there must be at least one.
|
||||||
func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (types []Type, index int) {
|
func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (types []Type, index int) {
|
||||||
assert(len(tparams) >= len(targs) && len(targs) > 0)
|
assert(len(tparams) >= len(targs) && len(targs) > 0)
|
||||||
|
|
||||||
// Setup bidirectional unification between those structural bounds
|
// Setup bidirectional unification between those structural bounds
|
||||||
@ -378,12 +378,12 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty
|
|||||||
|
|
||||||
// Unify type parameters with their structural constraints, if any.
|
// Unify type parameters with their structural constraints, if any.
|
||||||
for _, tpar := range tparams {
|
for _, tpar := range tparams {
|
||||||
typ := tpar.typ.(*TypeParam)
|
typ := tpar
|
||||||
sbound := typ.structuralType()
|
sbound := typ.structuralType()
|
||||||
if sbound != nil {
|
if sbound != nil {
|
||||||
if !u.unify(typ, sbound) {
|
if !u.unify(typ, sbound) {
|
||||||
if report {
|
if report {
|
||||||
check.errorf(tpar, _Todo, "%s does not match %s", tpar, sbound)
|
check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound)
|
||||||
}
|
}
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type,
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if validate {
|
if validate {
|
||||||
var tparams []*TypeName
|
var tparams []*TypeParam
|
||||||
switch t := typ.(type) {
|
switch t := typ.(type) {
|
||||||
case *Named:
|
case *Named:
|
||||||
tparams = t.TParams().list()
|
tparams = t.TParams().list()
|
||||||
@ -90,7 +90,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList
|
|||||||
check.later(func() {
|
check.later(func() {
|
||||||
// Collect tparams again because lazily loaded *Named types may not have
|
// Collect tparams again because lazily loaded *Named types may not have
|
||||||
// had tparams set up above.
|
// had tparams set up above.
|
||||||
var tparams []*TypeName
|
var tparams []*TypeParam
|
||||||
switch t := typ.(type) {
|
switch t := typ.(type) {
|
||||||
case *Named:
|
case *Named:
|
||||||
tparams = t.TParams().list()
|
tparams = t.TParams().list()
|
||||||
@ -186,11 +186,11 @@ func (check *Checker) validateTArgLen(pos token.Pos, tparams *TParamList, targs
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type) (int, error) {
|
func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) {
|
||||||
smap := makeSubstMap(tparams, targs)
|
smap := makeSubstMap(tparams, targs)
|
||||||
for i, tname := range tparams {
|
for i, tpar := range tparams {
|
||||||
// stop checking bounds after the first failure
|
// stop checking bounds after the first failure
|
||||||
if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil {
|
if err := check.satisfies(pos, targs[i], tpar, smap); err != nil {
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ type Named struct {
|
|||||||
targs []Type // type arguments (after instantiation), or nil
|
targs []Type // type arguments (after instantiation), or nil
|
||||||
methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily
|
methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily
|
||||||
|
|
||||||
resolve func(*Named) ([]*TypeName, Type, []*Func)
|
resolve func(*Named) ([]*TypeParam, Type, []*Func)
|
||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ func (t *Named) _Orig() *Named { return t.orig }
|
|||||||
func (t *Named) TParams() *TParamList { return t.load().tparams }
|
func (t *Named) TParams() *TParamList { return t.load().tparams }
|
||||||
|
|
||||||
// SetTParams sets the type parameters of the named type t.
|
// SetTParams sets the type parameters of the named type t.
|
||||||
func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) }
|
func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) }
|
||||||
|
|
||||||
// NumTArgs returns the number of type arguments used to instantiate the named
|
// NumTArgs returns the number of type arguments used to instantiate the named
|
||||||
// type t, or 0 if t is not an instantiated type.
|
// type t, or 0 if t is not an instantiated type.
|
||||||
|
@ -232,7 +232,7 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
|
|||||||
|
|
||||||
// _NewTypeNameLazy returns a new defined type like NewTypeName, but it
|
// _NewTypeNameLazy returns a new defined type like NewTypeName, but it
|
||||||
// lazily calls resolve to finish constructing the Named object.
|
// lazily calls resolve to finish constructing the Named object.
|
||||||
func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeName, underlying Type, methods []*Func)) *TypeName {
|
func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName {
|
||||||
obj := NewTypeName(pos, pkg, name, nil)
|
obj := NewTypeName(pos, pkg, name, nil)
|
||||||
NewNamed(obj, nil, nil).resolve = resolve
|
NewNamed(obj, nil, nil).resolve = resolve
|
||||||
return obj
|
return obj
|
||||||
|
@ -351,13 +351,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool {
|
func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool {
|
||||||
if len(x) != len(y) {
|
if len(x) != len(y) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i, x := range x {
|
for i, x := range x {
|
||||||
y := y[i]
|
y := y[i]
|
||||||
if !identical(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) {
|
if !identical(x.bound, y.bound, cmpTags, p) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,13 +59,13 @@ func (s *Signature) Recv() *Var { return s.recv }
|
|||||||
func (s *Signature) TParams() *TParamList { return s.tparams }
|
func (s *Signature) TParams() *TParamList { return s.tparams }
|
||||||
|
|
||||||
// SetTParams sets the type parameters of signature s.
|
// SetTParams sets the type parameters of signature s.
|
||||||
func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) }
|
func (s *Signature) SetTParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) }
|
||||||
|
|
||||||
// RParams returns the receiver type parameters of signature s, or nil.
|
// RParams returns the receiver type parameters of signature s, or nil.
|
||||||
func (s *Signature) RParams() *TParamList { return s.rparams }
|
func (s *Signature) RParams() *TParamList { return s.rparams }
|
||||||
|
|
||||||
// SetRParams sets the receiver type params of signature s.
|
// SetRParams sets the receiver type params of signature s.
|
||||||
func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) }
|
func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) }
|
||||||
|
|
||||||
// Params returns the parameters of signature s, or nil.
|
// Params returns the parameters of signature s, or nil.
|
||||||
func (s *Signature) Params() *Tuple { return s.params }
|
func (s *Signature) Params() *Tuple { return s.params }
|
||||||
@ -121,7 +121,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
|||||||
sig.rparams = bindTParams(check.declareTypeParams(nil, rparams))
|
sig.rparams = bindTParams(check.declareTypeParams(nil, rparams))
|
||||||
// determine receiver type to get its type parameters
|
// determine receiver type to get its type parameters
|
||||||
// and the respective type parameter bounds
|
// and the respective type parameter bounds
|
||||||
var recvTParams []*TypeName
|
var recvTParams []*TypeParam
|
||||||
if rname != nil {
|
if rname != nil {
|
||||||
// recv should be a Named type (otherwise an error is reported elsewhere)
|
// recv should be a Named type (otherwise an error is reported elsewhere)
|
||||||
// Also: Don't report an error via genericType since it will be reported
|
// Also: Don't report an error via genericType since it will be reported
|
||||||
@ -137,19 +137,19 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
|
|||||||
// We have a list of *TypeNames but we need a list of Types.
|
// We have a list of *TypeNames but we need a list of Types.
|
||||||
list := make([]Type, sig.RParams().Len())
|
list := make([]Type, sig.RParams().Len())
|
||||||
for i, t := range sig.RParams().list() {
|
for i, t := range sig.RParams().list() {
|
||||||
list[i] = t.typ
|
list[i] = t
|
||||||
}
|
}
|
||||||
smap := makeSubstMap(recvTParams, list)
|
smap := makeSubstMap(recvTParams, list)
|
||||||
for i, tname := range sig.RParams().list() {
|
for i, tpar := range sig.RParams().list() {
|
||||||
bound := recvTParams[i].typ.(*TypeParam).bound
|
bound := recvTParams[i].bound
|
||||||
// bound is (possibly) parameterized in the context of the
|
// bound is (possibly) parameterized in the context of the
|
||||||
// receiver type declaration. Substitute parameters for the
|
// receiver type declaration. Substitute parameters for the
|
||||||
// current context.
|
// current context.
|
||||||
// TODO(gri) should we assume now that bounds always exist?
|
// TODO(gri) should we assume now that bounds always exist?
|
||||||
// (no bound == empty interface)
|
// (no bound == empty interface)
|
||||||
if bound != nil {
|
if bound != nil {
|
||||||
bound = check.subst(tname.pos, bound, smap, nil)
|
bound = check.subst(tpar.obj.pos, bound, smap, nil)
|
||||||
tname.typ.(*TypeParam).bound = bound
|
tpar.bound = bound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@ type substMap map[*TypeParam]Type
|
|||||||
|
|
||||||
// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
|
// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
|
||||||
// If targs[i] is nil, tpars[i] is not substituted.
|
// If targs[i] is nil, tpars[i] is not substituted.
|
||||||
func makeSubstMap(tpars []*TypeName, targs []Type) substMap {
|
func makeSubstMap(tpars []*TypeParam, targs []Type) substMap {
|
||||||
assert(len(tpars) == len(targs))
|
assert(len(tpars) == len(targs))
|
||||||
proj := make(substMap, len(tpars))
|
proj := make(substMap, len(tpars))
|
||||||
for i, tpar := range tpars {
|
for i, tpar := range tpars {
|
||||||
proj[tpar.typ.(*TypeParam)] = targs[i]
|
proj[tpar] = targs[i]
|
||||||
}
|
}
|
||||||
return proj
|
return proj
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func (t *TypeParam) Underlying() Type { return t }
|
|||||||
func (t *TypeParam) String() string { return TypeString(t, nil) }
|
func (t *TypeParam) String() string { return TypeString(t, nil) }
|
||||||
|
|
||||||
// TParamList holds a list of type parameters bound to a type.
|
// TParamList holds a list of type parameters bound to a type.
|
||||||
type TParamList struct{ tparams []*TypeName }
|
type TParamList struct{ tparams []*TypeParam }
|
||||||
|
|
||||||
// Len returns the number of type parameters in the list.
|
// Len returns the number of type parameters in the list.
|
||||||
// It is safe to call on a nil receiver.
|
// It is safe to call on a nil receiver.
|
||||||
@ -98,23 +98,22 @@ func (tps *TParamList) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// At returns the i'th type parameter in the list.
|
// At returns the i'th type parameter in the list.
|
||||||
func (tps *TParamList) At(i int) *TypeName {
|
func (tps *TParamList) At(i int) *TypeParam {
|
||||||
return tps.list()[i]
|
return tps.list()[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tps *TParamList) list() []*TypeName {
|
func (tps *TParamList) list() []*TypeParam {
|
||||||
if tps == nil {
|
if tps == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return tps.tparams
|
return tps.tparams
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindTParams(list []*TypeName) *TParamList {
|
func bindTParams(list []*TypeParam) *TParamList {
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for i, tp := range list {
|
for i, typ := range list {
|
||||||
typ := tp.Type().(*TypeParam)
|
|
||||||
if typ.index >= 0 {
|
if typ.index >= 0 {
|
||||||
panic("type parameter bound more than once")
|
panic("type parameter bound more than once")
|
||||||
}
|
}
|
||||||
|
@ -244,15 +244,14 @@ func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) {
|
func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited []Type) {
|
||||||
// TODO(rFindley) compare this with the corresponding implementation in types2
|
// TODO(rFindley) compare this with the corresponding implementation in types2
|
||||||
buf.WriteString("[")
|
buf.WriteString("[")
|
||||||
var prev Type
|
var prev Type
|
||||||
for i, p := range list {
|
for i, tpar := range list {
|
||||||
// Determine the type parameter and its constraint.
|
// Determine the type parameter and its constraint.
|
||||||
// list is expected to hold type parameter names,
|
// list is expected to hold type parameter names,
|
||||||
// but don't crash if that's not the case.
|
// but don't crash if that's not the case.
|
||||||
tpar, _ := p.typ.(*TypeParam)
|
|
||||||
var bound Type
|
var bound Type
|
||||||
if tpar != nil {
|
if tpar != nil {
|
||||||
bound = tpar.bound // should not be nil but we want to see it if it is
|
bound = tpar.bound // should not be nil but we want to see it if it is
|
||||||
@ -271,7 +270,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited
|
|||||||
if tpar != nil {
|
if tpar != nil {
|
||||||
writeType(buf, tpar, qf, visited)
|
writeType(buf, tpar, qf, visited)
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(p.name)
|
buf.WriteString(tpar.obj.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if prev != nil {
|
if prev != nil {
|
||||||
|
@ -63,7 +63,7 @@ func (u *unifier) unify(x, y Type) bool {
|
|||||||
// A tparamsList describes a list of type parameters and the types inferred for them.
|
// A tparamsList describes a list of type parameters and the types inferred for them.
|
||||||
type tparamsList struct {
|
type tparamsList struct {
|
||||||
unifier *unifier
|
unifier *unifier
|
||||||
tparams []*TypeName
|
tparams []*TypeParam
|
||||||
// For each tparams element, there is a corresponding type slot index in indices.
|
// For each tparams element, there is a corresponding type slot index in indices.
|
||||||
// index < 0: unifier.types[-index-1] == nil
|
// index < 0: unifier.types[-index-1] == nil
|
||||||
// index == 0: no type slot allocated yet
|
// index == 0: no type slot allocated yet
|
||||||
@ -78,11 +78,11 @@ type tparamsList struct {
|
|||||||
func (d *tparamsList) String() string {
|
func (d *tparamsList) String() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.WriteByte('[')
|
buf.WriteByte('[')
|
||||||
for i, tname := range d.tparams {
|
for i, tpar := range d.tparams {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
buf.WriteString(", ")
|
buf.WriteString(", ")
|
||||||
}
|
}
|
||||||
writeType(&buf, tname.typ, nil, nil)
|
writeType(&buf, tpar, nil, nil)
|
||||||
buf.WriteString(": ")
|
buf.WriteString(": ")
|
||||||
writeType(&buf, d.at(i), nil, nil)
|
writeType(&buf, d.at(i), nil, nil)
|
||||||
}
|
}
|
||||||
@ -93,13 +93,13 @@ func (d *tparamsList) String() string {
|
|||||||
// init initializes d with the given type parameters.
|
// init initializes d with the given type parameters.
|
||||||
// The type parameters must be in the order in which they appear in their declaration
|
// The type parameters must be in the order in which they appear in their declaration
|
||||||
// (this ensures that the tparams indices match the respective type parameter index).
|
// (this ensures that the tparams indices match the respective type parameter index).
|
||||||
func (d *tparamsList) init(tparams []*TypeName) {
|
func (d *tparamsList) init(tparams []*TypeParam) {
|
||||||
if len(tparams) == 0 {
|
if len(tparams) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debug {
|
if debug {
|
||||||
for i, tpar := range tparams {
|
for i, tpar := range tparams {
|
||||||
assert(i == tpar.typ.(*TypeParam).index)
|
assert(i == tpar.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.tparams = tparams
|
d.tparams = tparams
|
||||||
@ -155,8 +155,8 @@ func (d *tparamsList) index(typ Type) int {
|
|||||||
|
|
||||||
// If tpar is a type parameter in list, tparamIndex returns the type parameter index.
|
// If tpar is a type parameter in list, tparamIndex returns the type parameter index.
|
||||||
// Otherwise, the result is < 0. tpar must not be nil.
|
// Otherwise, the result is < 0. tpar must not be nil.
|
||||||
func tparamIndex(list []*TypeName, tpar *TypeParam) int {
|
func tparamIndex(list []*TypeParam, tpar *TypeParam) int {
|
||||||
if i := tpar.index; i < len(list) && list[i].typ == tpar {
|
if i := tpar.index; i < len(list) && list[i] == tpar {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
|
Loading…
Reference in New Issue
Block a user