aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/typecheck/iexport.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/typecheck/iexport.go')
-rw-r--r--src/cmd/compile/internal/typecheck/iexport.go97
1 files changed, 90 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index 3538c4d5a6..11b9755148 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -173,6 +173,8 @@
// }
//
//
+// TODO(danscales): fill in doc for 'type TypeParamType' and 'type InstType'
+//
// type Signature struct {
// Params []Param
// Results []Param
@@ -244,6 +246,8 @@ const (
signatureType
structType
interfaceType
+ typeParamType
+ instType
)
const (
@@ -459,6 +463,13 @@ func (p *iexporter) doDecl(n *ir.Name) {
// Function.
w.tag('F')
w.pos(n.Pos())
+ // The tparam list of the function type is the
+ // declaration of the type params. So, write out the type
+ // params right now. Then those type params will be
+ // referenced via their type offset (via typOff) in all
+ // other places in the signature and function that they
+ // are used.
+ w.tparamList(n.Type().TParams().FieldSlice())
w.signature(n.Type())
w.funcExt(n)
@@ -491,6 +502,8 @@ func (p *iexporter) doDecl(n *ir.Name) {
w.tag('T')
w.pos(n.Pos())
+ // Export any new typeparams needed for this type
+ w.typeList(n.Type().RParams())
underlying := n.Type().Underlying()
if underlying == types.ErrorType.Underlying() {
// For "type T error", use error as the
@@ -803,8 +816,49 @@ func (w *exportWriter) startType(k itag) {
}
func (w *exportWriter) doTyp(t *types.Type) {
- if t.Sym() != nil {
- if t.Sym().Pkg == types.BuiltinPkg || t.Sym().Pkg == ir.Pkgs.Unsafe {
+ if t.Kind() == types.TTYPEPARAM {
+ // A typeparam has a name, but doesn't have an underlying type.
+ // Just write out the details of the type param here. All other
+ // uses of this typeparam type will be written out as its unique
+ // type offset.
+ w.startType(typeParamType)
+ s := t.Sym()
+ w.setPkg(s.Pkg, true)
+ w.pos(t.Pos())
+
+ // We are writing out the name with the subscript, so that the
+ // typeparam name is unique.
+ w.string(s.Name)
+ w.int64(int64(t.Index()))
+
+ w.typ(t.Bound())
+ return
+ }
+
+ s := t.Sym()
+ if s != nil && t.OrigSym != nil {
+ // This is an instantiated type - could be a re-instantiation like
+ // Value[T2] or a full instantiation like Value[int].
+ if strings.Index(s.Name, "[") < 0 {
+ base.Fatalf("incorrect name for instantiated type")
+ }
+ w.startType(instType)
+ w.pos(t.Pos())
+ // Export the type arguments for the instantiated type. The
+ // instantiated type could be in a method header (e.g. "func (v
+ // *Value[T2]) set (...) { ... }"), so the type args are "new"
+ // typeparams. Or the instantiated type could be in a
+ // function/method body, so the type args are either concrete
+ // types or existing typeparams from the function/method header.
+ w.typeList(t.RParams())
+ // Export a reference to the base type.
+ baseType := t.OrigSym.Def.(*ir.Name).Type()
+ w.typ(baseType)
+ return
+ }
+
+ if s != nil {
+ if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe {
base.Fatalf("builtin type missing from typIndex: %v", t)
}
@@ -906,6 +960,23 @@ func (w *exportWriter) signature(t *types.Type) {
}
}
+func (w *exportWriter) typeList(ts []*types.Type) {
+ w.uint64(uint64(len(ts)))
+ for _, rparam := range ts {
+ w.typ(rparam)
+ }
+}
+
+func (w *exportWriter) tparamList(fs []*types.Field) {
+ w.uint64(uint64(len(fs)))
+ for _, f := range fs {
+ if f.Type.Kind() != types.TTYPEPARAM {
+ base.Fatalf("unexpected non-typeparam")
+ }
+ w.typ(f.Type)
+ }
+}
+
func (w *exportWriter) paramList(fs []*types.Field) {
w.uint64(uint64(len(fs)))
for _, f := range fs {
@@ -1186,9 +1257,21 @@ func (w *exportWriter) funcExt(n *ir.Name) {
}
// Inline body.
+ if n.Type().HasTParam() {
+ if n.Func.Inl != nil {
+ base.FatalfAt(n.Pos(), "generic function is marked inlineable")
+ }
+ // Populate n.Func.Inl, so body of exported generic function will
+ // be written out.
+ n.Func.Inl = &ir.Inline{
+ Cost: 1,
+ Dcl: n.Func.Dcl,
+ Body: n.Func.Body,
+ }
+ }
if n.Func.Inl != nil {
w.uint64(1 + uint64(n.Func.Inl.Cost))
- if n.Func.ExportInline() {
+ if n.Func.ExportInline() || n.Type().HasTParam() {
w.p.doInline(n)
}
@@ -1588,9 +1671,8 @@ func (w *exportWriter) expr(n ir.Node) {
case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR:
n := n.(*ir.SelectorExpr)
if go117ExportTypes {
- if n.Op() == ir.OXDOT {
- base.Fatalf("shouldn't encounter XDOT in new exporter")
- }
+ // For go117ExportTypes, we usually see all ops except
+ // OXDOT, but we can see OXDOT for generic functions.
w.op(n.Op())
} else {
w.op(ir.OXDOT)
@@ -1604,7 +1686,8 @@ func (w *exportWriter) expr(n ir.Node) {
w.exoticField(n.Selection)
}
// n.Selection is not required for OMETHEXPR, ODOTMETH, and OCALLPART. It will
- // be reconstructed during import.
+ // be reconstructed during import. n.Selection is computed during
+ // transformDot() for OXDOT.
}
case ir.ODOTTYPE, ir.ODOTTYPE2: