conf.go115UsesCgo = true
}
+// Info holds result type information for a type-checked package.
+// Only the information for which a map is provided is collected.
+// If the package has type errors, the collected information may
+// be incomplete.
+type Info struct {
+ // Types maps expressions to their types, and for constant
+ // expressions, also their values. Invalid expressions are
+ // omitted.
+ //
+ // For (possibly parenthesized) identifiers denoting built-in
+ // functions, the recorded signatures are call-site specific:
+ // if the call result is not a constant, the recorded type is
+ // an argument-specific signature. Otherwise, the recorded type
+ // is invalid.
+ //
+ // The Types map does not record the type of every identifier,
+ // only those that appear where an arbitrary expression is
+ // permitted. For instance, the identifier f in a selector
+ // expression x.f is found only in the Selections map, the
+ // identifier z in a variable declaration 'var z int' is found
+ // only in the Defs map, and identifiers denoting packages in
+ // qualified identifiers are collected in the Uses map.
+ Types map[ast.Expr]TypeAndValue
+
+ // Inferred maps calls of parameterized functions that use
+ // type inference to the inferred type arguments and signature
+ // of the function called. The recorded "call" expression may be
+ // an *ast.CallExpr (as in f(x)), or an *ast.IndexExpr (s in f[T]).
+ Inferred map[ast.Expr]Inferred
+
+ // Defs maps identifiers to the objects they define (including
+ // package names, dots "." of dot-imports, and blank "_" identifiers).
+ // For identifiers that do not denote objects (e.g., the package name
+ // in package clauses, or symbolic variables t in t := x.(type) of
+ // type switch headers), the corresponding objects are nil.
+ //
+ // For an embedded field, Defs returns the field *Var it defines.
+ //
+ // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
+ Defs map[*ast.Ident]Object
+
+ // Uses maps identifiers to the objects they denote.
+ //
+ // For an embedded field, Uses returns the *TypeName it denotes.
+ //
+ // Invariant: Uses[id].Pos() != id.Pos()
+ Uses map[*ast.Ident]Object
+
+ // Implicits maps nodes to their implicitly declared objects, if any.
+ // The following node and object types may appear:
+ //
+ // node declared object
+ //
+ // *ast.ImportSpec *PkgName for imports without renames
+ // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
+ // *ast.Field anonymous parameter *Var (incl. unnamed results)
+ //
+ Implicits map[ast.Node]Object
+
+ // Selections maps selector expressions (excluding qualified identifiers)
+ // to their corresponding selections.
+ Selections map[*ast.SelectorExpr]*Selection
+
+ // Scopes maps ast.Nodes to the scopes they define. Package scopes are not
+ // associated with a specific node but with all files belonging to a package.
+ // Thus, the package scope can be found in the type-checked Package object.
+ // Scopes nest, with the Universe scope being the outermost scope, enclosing
+ // the package scope, which contains (one or more) files scopes, which enclose
+ // function scopes which in turn enclose statement and function literal scopes.
+ // Note that even though package-level functions are declared in the package
+ // scope, the function scopes are embedded in the file scope of the file
+ // containing the function declaration.
+ //
+ // The following node types may appear in Scopes:
+ //
+ // *ast.File
+ // *ast.FuncType
+ // *ast.BlockStmt
+ // *ast.IfStmt
+ // *ast.SwitchStmt
+ // *ast.TypeSwitchStmt
+ // *ast.CaseClause
+ // *ast.CommClause
+ // *ast.ForStmt
+ // *ast.RangeStmt
+ //
+ Scopes map[ast.Node]*Scope
+
+ // InitOrder is the list of package-level initializers in the order in which
+ // they must be executed. Initializers referring to variables related by an
+ // initialization dependency appear in topological order, the others appear
+ // in source order. Variables without an initialization expression do not
+ // appear in this list.
+ InitOrder []*Initializer
+}
+
// The Info struct is found in api_notypeparams.go and api_typeparams.go.
// TypeOf returns the type of expression e, or nil if not found.
return tv.mode == commaok || tv.mode == mapindex
}
-// _Inferred reports the _Inferred type arguments and signature
+// Inferred reports the Inferred type arguments and signature
// for a parameterized function call that uses type inference.
-type _Inferred struct {
+type Inferred struct {
TArgs []Type
Sig *Signature
}
}
}
+func TestInferredInfo(t *testing.T) {
+ var tests = []struct {
+ src string
+ fun string
+ targs []string
+ sig string
+ }{
+ {genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
+ `f`,
+ []string{`int`},
+ `func(int)`,
+ },
+ {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
+ `f`,
+ []string{`rune`},
+ `func(rune) rune`,
+ },
+ {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
+ `f`,
+ []string{`complex128`},
+ `func(...complex128) complex128`,
+ },
+ {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
+ `f`,
+ []string{`float64`, `string`, `byte`},
+ `func(float64, *string, []byte)`,
+ },
+ {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
+ `f`,
+ []string{`float64`, `byte`},
+ `func(float64, *byte, ...[]byte)`,
+ },
+
+ {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`,
+ `f`,
+ []string{`string`, `*string`},
+ `func(x string)`,
+ },
+ {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`,
+ `f`,
+ []string{`int`, `*int`},
+ `func(x []int)`,
+ },
+ {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
+ `f`,
+ []string{`int`, `chan<- int`},
+ `func(x []int)`,
+ },
+ {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
+ `f`,
+ []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+ `func(x []int)`,
+ },
+
+ {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`,
+ `f`,
+ []string{`string`, `*string`},
+ `func() string`,
+ },
+ {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
+ `f`,
+ []string{`int`, `chan<- int`},
+ `func() []int`,
+ },
+ {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
+ `f`,
+ []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
+ `func() []int`,
+ },
+ }
+
+ for _, test := range tests {
+ info := Info{}
+ info.Inferred = make(map[ast.Expr]Inferred)
+ name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
+ if err != nil {
+ t.Errorf("package %s: %v", name, err)
+ continue
+ }
+
+ // look for inferred type arguments and signature
+ var targs []Type
+ var sig *Signature
+ for call, inf := range info.Inferred {
+ var fun ast.Expr
+ switch x := call.(type) {
+ case *ast.CallExpr:
+ fun = x.Fun
+ case *ast.IndexExpr:
+ fun = x.X
+ default:
+ panic(fmt.Sprintf("unexpected call expression type %T", call))
+ }
+ if ExprString(fun) == test.fun {
+ targs = inf.TArgs
+ sig = inf.Sig
+ break
+ }
+ }
+ if targs == nil {
+ t.Errorf("package %s: no inferred information found for %s", name, test.fun)
+ continue
+ }
+
+ // check that type arguments are correct
+ if len(targs) != len(test.targs) {
+ t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
+ continue
+ }
+ for i, targ := range targs {
+ if got := targ.String(); got != test.targs[i] {
+ t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
+ continue
+ }
+ }
+
+ // check that signature is correct
+ if got := sig.String(); got != test.sig {
+ t.Errorf("package %s: got %s; want %s", name, got, test.sig)
+ }
+ }
+}
+
func TestDefsInfo(t *testing.T) {
var tests = []struct {
src string
+++ /dev/null
-// Copyright 2021 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 types
-
-import (
- "go/ast"
-)
-
-type (
- Inferred = _Inferred
- TypeParam = _TypeParam
-)
-
-// NewTypeParam returns a new TypeParam.
-func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
- return (*Checker)(nil).newTypeParam(obj, index, bound)
-}
-
-func (s *Signature) TParams() []*TypeName { return s._TParams() }
-func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) }
-
-func (t *Named) TParams() []*TypeName { return t._TParams() }
-func (t *Named) TArgs() []Type { return t._TArgs() }
-func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) }
-
-// Info is documented in api_notypeparams.go.
-type Info struct {
- Types map[ast.Expr]TypeAndValue
-
- // Inferred maps calls of parameterized functions that use type inference to
- // the Inferred type arguments and signature of the function called. The
- // recorded "call" expression may be an *ast.CallExpr (as in f(x)), or an
- // *ast.IndexExpr (s in f[T]).
- Inferred map[ast.Expr]_Inferred
-
- Defs map[*ast.Ident]Object
- Uses map[*ast.Ident]Object
- Implicits map[ast.Node]Object
- Selections map[*ast.SelectorExpr]*Selection
- Scopes map[ast.Node]*Scope
- InitOrder []*Initializer
-}
-
-func getInferred(info *Info) map[ast.Expr]_Inferred {
- return info.Inferred
-}
+++ /dev/null
-// Copyright 2021 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 types_test
-
-import (
- "fmt"
- "go/ast"
- "testing"
-
- . "go/types"
-)
-
-func TestInferredInfo(t *testing.T) {
- var tests = []struct {
- src string
- fun string
- targs []string
- sig string
- }{
- {genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
- `f`,
- []string{`int`},
- `func(int)`,
- },
- {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
- `f`,
- []string{`rune`},
- `func(rune) rune`,
- },
- {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
- `f`,
- []string{`complex128`},
- `func(...complex128) complex128`,
- },
- {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
- `f`,
- []string{`float64`, `string`, `byte`},
- `func(float64, *string, []byte)`,
- },
- {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
- `f`,
- []string{`float64`, `byte`},
- `func(float64, *byte, ...[]byte)`,
- },
-
- {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`,
- `f`,
- []string{`string`, `*string`},
- `func(x string)`,
- },
- {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `*int`},
- `func(x []int)`,
- },
- {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`},
- `func(x []int)`,
- },
- {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func(x []int)`,
- },
-
- {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`,
- `f`,
- []string{`string`, `*string`},
- `func() string`,
- },
- {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`},
- `func() []int`,
- },
- {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
- `f`,
- []string{`int`, `chan<- int`, `chan<- []*chan<- int`},
- `func() []int`,
- },
- }
-
- for _, test := range tests {
- info := Info{}
- info.Inferred = make(map[ast.Expr]Inferred)
- name, err := mayTypecheck(t, "InferredInfo", test.src, &info)
- if err != nil {
- t.Errorf("package %s: %v", name, err)
- continue
- }
-
- // look for inferred type arguments and signature
- var targs []Type
- var sig *Signature
- for call, inf := range info.Inferred {
- var fun ast.Expr
- switch x := call.(type) {
- case *ast.CallExpr:
- fun = x.Fun
- case *ast.IndexExpr:
- fun = x.X
- default:
- panic(fmt.Sprintf("unexpected call expression type %T", call))
- }
- if ExprString(fun) == test.fun {
- targs = inf.TArgs
- sig = inf.Sig
- break
- }
- }
- if targs == nil {
- t.Errorf("package %s: no inferred information found for %s", name, test.fun)
- continue
- }
-
- // check that type arguments are correct
- if len(targs) != len(test.targs) {
- t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs))
- continue
- }
- for i, targ := range targs {
- if got := targ.String(); got != test.targs[i] {
- t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i])
- continue
- }
- }
-
- // check that signature is correct
- if got := sig.String(); got != test.sig {
- t.Errorf("package %s: got %s; want %s", name, got, test.sig)
- }
- }
-}
func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) {
assert(call != nil)
assert(sig != nil)
- if m := getInferred(check.Info); m != nil {
- m[call] = _Inferred{targs, sig}
+ if m := check.Info.Inferred; m != nil {
+ m[call] = Inferred{targs, sig}
}
}
setBoundAt := func(at int, bound Type) {
assert(IsInterface(bound))
- tparams[at].typ.(*_TypeParam).bound = bound
+ tparams[at].typ.(*TypeParam).bound = bound
}
index := 0
tkey = t.key
e = t.elem
nmaps++
- case *_TypeParam:
+ case *TypeParam:
check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x)
case *instance:
panic("unimplemented")
valid = true
// x.typ doesn't change
- case *Union, *_TypeParam:
+ case *Union, *TypeParam:
check.errorf(x, 0, "generic slice expressions not yet implemented")
x.mode = invalid
return
// only parameter type it can possibly match against is a *TypeParam.
// Thus, only consider untyped arguments for generic parameters that
// are not of composite types and which don't have a type inferred yet.
- if tpar, _ := par.typ.(*_TypeParam); tpar != nil && targs[tpar.index] == nil {
+ if tpar, _ := par.typ.(*TypeParam); tpar != nil && targs[tpar.index] == nil {
arg := args[i]
targ := Default(arg.typ)
// The default type for an untyped nil is untyped nil. We must not
case *Named:
return w.isParameterizedList(t.targs)
- case *_TypeParam:
+ case *TypeParam:
// t must be one of w.tparams
return t.index < len(w.tparams) && w.tparams[t.index].typ == t
// Unify type parameters with their structural constraints, if any.
for _, tpar := range tparams {
- typ := tpar.typ.(*_TypeParam)
+ typ := tpar.typ.(*TypeParam)
sbound := check.structuralType(typ.bound)
if sbound != nil {
if !u.unify(typ, sbound) {
var next []embeddedType // embedded types found at current depth
// look for (pkg, name) in all types at current depth
- var tpar *_TypeParam // set if obj receiver is a type parameter
+ var tpar *TypeParam // set if obj receiver is a type parameter
for _, e := range current {
typ := e.typ
indirect = e.indirect
}
- case *_TypeParam:
+ case *TypeParam:
if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil {
assert(m.typ != nil)
index = concat(e.index, i)
// continue with underlying type, but only if it's not a type parameter
// TODO(rFindley): should this use named.under()? Can there be a difference?
typ = named.underlying
- if _, ok := typ.(*_TypeParam); ok {
+ if _, ok := typ.(*TypeParam); ok {
continue
}
}
case *Interface:
mset = mset.add(t.typeSet().methods, e.index, true, e.multiples)
- case *_TypeParam:
+ case *TypeParam:
mset = mset.add(t.Bound().typeSet().methods, e.index, true, e.multiples)
}
}
// isNamed may be called with types that are not fully set up.
func isNamed(typ Type) bool {
switch typ.(type) {
- case *Basic, *Named, *_TypeParam, *instance:
+ case *Basic, *Named, *TypeParam, *instance:
return true
}
return false
return t.underIs(func(t Type) bool {
return comparable(t, seen)
})
- case *_TypeParam:
+ case *TypeParam:
return t.Bound().IsComparable()
}
return false
return x.obj == y.obj
}
- case *_TypeParam:
+ case *TypeParam:
// nothing to do (x and y being equal is caught in the very beginning of this function)
// case *instance:
}
for i, x := range x {
y := y[i]
- if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) {
+ if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) {
return false
}
}
}
}
- inferred := getInferred(info)
+ inferred := info.Inferred
for e, inf := range inferred {
changed := false
for i, targ := range inf.TArgs {
s.typeList(t.targs)
s.funcList(t.methods)
- case *_TypeParam:
+ case *TypeParam:
if bound := s.typ(t.bound); bound != t.bound {
t.bound = bound
}
}
smap := makeSubstMap(recvTParams, list)
for i, tname := range sig.rparams {
- bound := recvTParams[i].typ.(*_TypeParam).bound
+ bound := recvTParams[i].typ.(*TypeParam).bound
// bound is (possibly) parameterized in the context of the
// receiver type declaration. Substitute parameters for the
// current context.
// (no bound == empty interface)
if bound != nil {
bound = check.subst(tname.pos, bound, smap)
- tname.typ.(*_TypeParam).bound = bound
+ tname.typ.(*TypeParam).bound = bound
}
}
}
{Map{}, 16, 32},
{Chan{}, 12, 24},
{Named{}, 84, 160},
- {_TypeParam{}, 28, 48},
+ {TypeParam{}, 28, 48},
{instance{}, 44, 88},
{top{}, 0, 0},
// TODO(gri) rewrite that code, get rid of this field, and make this
// struct just the map (proj)
targs []Type
- proj map[*_TypeParam]Type
+ proj map[*TypeParam]Type
}
// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
// If targs[i] is nil, tpars[i] is not substituted.
func makeSubstMap(tpars []*TypeName, targs []Type) *substMap {
assert(len(tpars) == len(targs))
- proj := make(map[*_TypeParam]Type, len(tpars))
+ proj := make(map[*TypeParam]Type, len(tpars))
for i, tpar := range tpars {
// We must expand type arguments otherwise *instance
// types end up as components in composite types.
// TODO(gri) explain why this causes problems, if it does
targ := expand(targs[i]) // possibly nil
targs[i] = targ
- proj[tpar.typ.(*_TypeParam)] = targ
+ proj[tpar.typ.(*TypeParam)] = targ
}
return &substMap{targs, proj}
}
return len(m.proj) == 0
}
-func (m *substMap) lookup(tpar *_TypeParam) Type {
+func (m *substMap) lookup(tpar *TypeParam) Type {
if t := m.proj[tpar]; t != nil {
return t
}
}
// stop checking bounds after the first failure
- if !check.satisfies(pos, targs[i], tname.typ.(*_TypeParam), smap) {
+ if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) {
break
}
}
// parameter tpar (after any of its type parameters have been substituted through smap).
// A suitable error is reported if the result is false.
// TODO(gri) This should be a method of interfaces or type sets.
-func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap *substMap) bool {
+func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool {
iface := tpar.Bound()
if iface.Empty() {
return true // no type bound
switch t := typ.(type) {
case *Basic:
return typ // nothing to do
- case *_TypeParam:
+ case *TypeParam:
return smap.lookup(t)
}
return named
- case *_TypeParam:
+ case *TypeParam:
return subst.smap.lookup(t)
case *instance:
func (s *Signature) Recv() *Var { return s.recv }
// _TParams returns the type parameters of signature s, or nil.
-func (s *Signature) _TParams() []*TypeName { return s.tparams }
+func (s *Signature) TParams() []*TypeName { return s.tparams }
// _SetTParams sets the type parameters of signature s.
-func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams }
+func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams }
// Params returns the parameters of signature s, or nil.
func (s *Signature) Params() *Tuple { return s.params }
// _TParams returns the type parameters of the named type t, or nil.
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
-func (t *Named) _TParams() []*TypeName { return t.expand().tparams }
+func (t *Named) TParams() []*TypeName { return t.expand().tparams }
// _SetTParams sets the type parameters of the named type t.
-func (t *Named) _SetTParams(tparams []*TypeName) { t.expand().tparams = tparams }
+func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams }
// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
-func (t *Named) _TArgs() []Type { return t.targs }
+func (t *Named) TArgs() []Type { return t.targs }
// SetTArgs sets the type arguments of the named type t.
-func (t *Named) _SetTArgs(args []Type) { t.targs = args }
+func (t *Named) SetTArgs(args []Type) { t.targs = args }
// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.expand().methods) }
// each call, starting with 1. It may be called concurrently.
func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) }
-// A _TypeParam represents a type parameter type.
-type _TypeParam struct {
+// A TypeParam represents a type parameter type.
+type TypeParam struct {
check *Checker // for lazy type bound completion
id uint64 // unique id, for debugging only
obj *TypeName // corresponding type name
bound Type // *Named or *Interface; underlying type is always *Interface
}
-func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam {
+// NewTypeParam returns a new TypeParam.
+func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
+ return (*Checker)(nil).newTypeParam(obj, index, bound)
+}
+
+func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
assert(bound != nil)
// Always increment lastID, even if it is not used.
id = check.nextID
}
- typ := &_TypeParam{check: check, id: id, obj: obj, index: index, bound: bound}
+ typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound}
if obj.typ == nil {
obj.typ = typ
}
return typ
}
-func (t *_TypeParam) Bound() *Interface {
+func (t *TypeParam) Bound() *Interface {
iface := asInterface(t.bound)
// use the type bound position if we have one
pos := token.NoPos
var theTop = &top{}
// Type-specific implementations of Underlying.
-func (t *Basic) Underlying() Type { return t }
-func (t *Array) Underlying() Type { return t }
-func (t *Slice) Underlying() Type { return t }
-func (t *Struct) Underlying() Type { return t }
-func (t *Pointer) Underlying() Type { return t }
-func (t *Tuple) Underlying() Type { return t }
-func (t *Signature) Underlying() Type { return t }
-func (t *Interface) Underlying() Type { return t }
-func (t *Map) Underlying() Type { return t }
-func (t *Chan) Underlying() Type { return t }
-func (t *Named) Underlying() Type { return t.expand().underlying }
-func (t *_TypeParam) Underlying() Type { return t }
-func (t *instance) Underlying() Type { return t }
-func (t *top) Underlying() Type { return t }
+func (t *Basic) Underlying() Type { return t }
+func (t *Array) Underlying() Type { return t }
+func (t *Slice) Underlying() Type { return t }
+func (t *Struct) Underlying() Type { return t }
+func (t *Pointer) Underlying() Type { return t }
+func (t *Tuple) Underlying() Type { return t }
+func (t *Signature) Underlying() Type { return t }
+func (t *Interface) Underlying() Type { return t }
+func (t *Map) Underlying() Type { return t }
+func (t *Chan) Underlying() Type { return t }
+func (t *Named) Underlying() Type { return t.expand().underlying }
+func (t *TypeParam) Underlying() Type { return t }
+func (t *instance) Underlying() Type { return t }
+func (t *top) Underlying() Type { return t }
// Type-specific implementations of String.
-func (t *Basic) String() string { return TypeString(t, nil) }
-func (t *Array) String() string { return TypeString(t, nil) }
-func (t *Slice) String() string { return TypeString(t, nil) }
-func (t *Struct) String() string { return TypeString(t, nil) }
-func (t *Pointer) String() string { return TypeString(t, nil) }
-func (t *Tuple) String() string { return TypeString(t, nil) }
-func (t *Signature) String() string { return TypeString(t, nil) }
-func (t *Interface) String() string { return TypeString(t, nil) }
-func (t *Map) String() string { return TypeString(t, nil) }
-func (t *Chan) String() string { return TypeString(t, nil) }
-func (t *Named) String() string { return TypeString(t, nil) }
-func (t *_TypeParam) String() string { return TypeString(t, nil) }
-func (t *instance) String() string { return TypeString(t, nil) }
-func (t *top) String() string { return TypeString(t, nil) }
+func (t *Basic) String() string { return TypeString(t, nil) }
+func (t *Array) String() string { return TypeString(t, nil) }
+func (t *Slice) String() string { return TypeString(t, nil) }
+func (t *Struct) String() string { return TypeString(t, nil) }
+func (t *Pointer) String() string { return TypeString(t, nil) }
+func (t *Tuple) String() string { return TypeString(t, nil) }
+func (t *Signature) String() string { return TypeString(t, nil) }
+func (t *Interface) String() string { return TypeString(t, nil) }
+func (t *Map) String() string { return TypeString(t, nil) }
+func (t *Chan) String() string { return TypeString(t, nil) }
+func (t *Named) String() string { return TypeString(t, nil) }
+func (t *TypeParam) String() string { return TypeString(t, nil) }
+func (t *instance) String() string { return TypeString(t, nil) }
+func (t *top) String() string { return TypeString(t, nil) }
// under returns the true expanded underlying type.
// If it doesn't exist, the result is Typ[Invalid].
return e
}
-func asTypeParam(t Type) *_TypeParam {
- u, _ := under(t).(*_TypeParam)
+func asTypeParam(t Type) *TypeParam {
+ u, _ := under(t).(*TypeParam)
return u
}
writeTParamList(buf, t.TParams(), qf, visited)
}
- case *_TypeParam:
+ case *TypeParam:
s := "?"
if t.obj != nil {
s = t.obj.name
for i, p := range list {
// TODO(rFindley) support 'any' sugar here.
var b Type = &emptyInterface
- if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil {
+ if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil {
b = t.bound
}
if i > 0 {
}
prev = b
- if t, _ := p.typ.(*_TypeParam); t != nil {
+ if t, _ := p.typ.(*TypeParam); t != nil {
writeType(buf, t, qf, visited)
} else {
buf.WriteString(p.name)
}
if debug {
for i, tpar := range tparams {
- assert(i == tpar.typ.(*_TypeParam).index)
+ assert(i == tpar.typ.(*TypeParam).index)
}
}
d.tparams = tparams
// If typ is a type parameter of d, index returns the type parameter index.
// Otherwise, the result is < 0.
func (d *tparamsList) index(typ Type) int {
- if t, ok := typ.(*_TypeParam); ok {
+ if t, ok := typ.(*TypeParam); ok {
if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t {
return i
}
}
}
- case *_TypeParam:
+ case *TypeParam:
// Two type parameters (which are not part of the type parameters of the
// enclosing type as those are handled in the beginning of this function)
// are identical if they originate in the same declaration.