// A writerDict tracks types and objects that are used by a declaration.
type writerDict struct {
- implicits []*types2.TypeName
+ // implicits is a slice of type parameters from the enclosing
+ // declarations.
+ implicits []*types2.TypeParam
// derived is a slice of type indices for computing derived types
// (i.e., types that depend on the declaration's type parameters).
// generic function or method.
func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int {
for idx, implicit := range dict.implicits {
- if types2.Unalias(implicit.Type()).(*types2.TypeParam) == typ {
+ if implicit == typ {
return idx
}
}
w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx)
w.dict = dict
- switch typ := types2.Unalias(typ).(type) {
+ switch typ := typ.(type) {
default:
base.Fatalf("unexpected type: %v (%T)", typ, typ)
default:
// Handle "byte" and "rune" as references to their TypeNames.
- obj := types2.Universe.Lookup(typ.Name())
+ obj := types2.Universe.Lookup(typ.Name()).(*types2.TypeName)
assert(obj.Type() == typ)
w.Code(pkgbits.TypeNamed)
- w.obj(obj, nil)
+ w.namedType(obj, nil)
}
case *types2.Named:
- obj, targs := splitNamed(typ)
-
- // Defined types that are declared within a generic function (and
- // thus have implicit type parameters) are always derived types.
- if w.p.hasImplicitTypeParams(obj) {
- w.derived = true
- }
+ w.Code(pkgbits.TypeNamed)
+ w.namedType(splitNamed(typ))
+ case *types2.Alias:
w.Code(pkgbits.TypeNamed)
- w.obj(obj, targs)
+ w.namedType(typ.Obj(), nil)
case *types2.TypeParam:
w.derived = true
return typeInfo{idx: w.Flush(), derived: false}
}
+// namedType writes a use of the given named type into the bitstream.
+func (w *writer) namedType(obj *types2.TypeName, targs *types2.TypeList) {
+ // Named types that are declared within a generic function (and
+ // thus have implicit type parameters) are always derived types.
+ if w.p.hasImplicitTypeParams(obj) {
+ w.derived = true
+ }
+
+ w.obj(obj, targs)
+}
+
func (w *writer) structType(typ *types2.Struct) {
w.Len(typ.NumFields())
for i := 0; i < typ.NumFields(); i++ {
// parameter is constrained to `int | uint` but then never used in
// arithmetic/conversions/etc, we could shape those together.
for _, implicit := range dict.implicits {
- tparam := types2.Unalias(implicit.Type()).(*types2.TypeParam)
- w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
+ w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
}
for i := 0; i < ntparams; i++ {
tparam := tparams.At(i)
}
}
+// isUntyped reports whether typ is an untyped type.
func isUntyped(typ types2.Type) bool {
- basic, ok := types2.Unalias(typ).(*types2.Basic)
+ // Note: types2.Unalias is unnecessary here, since untyped types can't be aliased.
+ basic, ok := typ.(*types2.Basic)
return ok && basic.Info()&types2.IsUntyped != 0
}
+// isTuple reports whether typ is a tuple type.
func isTuple(typ types2.Type) bool {
+ // Note: types2.Unalias is unnecessary here, since tuple types can't be aliased.
_, ok := typ.(*types2.Tuple)
return ok
}
gen int
// Implicit type parameters in scope at this type declaration.
- implicits []*types2.TypeName
+ implicits []*types2.TypeParam
}
type fileImports struct {
typegen *int
file *fileImports
withinFunc bool
- implicits []*types2.TypeName
+ implicits []*types2.TypeParam
}
func (c *declCollector) withTParams(obj types2.Object) *declCollector {
copy := *c
copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
for i := 0; i < n; i++ {
- copy.implicits = append(copy.implicits, tparams.At(i).Obj())
+ copy.implicits = append(copy.implicits, tparams.At(i))
}
return ©
}
func recvBase(recv *types2.Var) *types2.Named {
typ := types2.Unalias(recv.Type())
if ptr, ok := typ.(*types2.Pointer); ok {
- typ = ptr.Elem()
+ typ = types2.Unalias(ptr.Elem())
}
return typ.(*types2.Named)
}