// Keep this in sync with constants in iexport.go.
const (
- iexportVersionGo1_11 = 0
- iexportVersionPosCol = 1
- // TODO: before release, change this back to 2.
- iexportVersionGenerics = iexportVersionPosCol
+ iexportVersionGo1_11 = 0
+ iexportVersionPosCol = 1
+ iexportVersionGenerics = 1 // probably change to 2 before release
+ iexportVersionGo1_18 = 2
- iexportVersionCurrent = iexportVersionGenerics
+ iexportVersionCurrent = 2
)
type ident struct {
version = int64(r.uint64())
switch version {
- case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
+ case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default:
- if version > iexportVersionGenerics {
- errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
- } else {
- errorf("unknown iexport format version %d", version)
- }
+ errorf("unknown iexport format version %d", version)
}
sLen := int64(r.uint64())
id := ident{r.currPkg.Name(), name}
r.p.tparamIndex[id] = t
- t.SetConstraint(r.typ())
+ var implicit bool
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ implicit = r.bool()
+ }
+ constraint := r.typ()
+ if implicit {
+ iface, _ := constraint.(*types2.Interface)
+ if iface == nil {
+ errorf("non-interface constraint marked implicit")
+ }
+ iface.MarkImplicit()
+ }
+ t.SetConstraint(constraint)
case 'V':
typ := r.typ()
func (r *importReader) value() (typ types2.Type, val constant.Value) {
typ = r.typ()
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ // TODO: add support for using the kind
+ _ = constant.Kind(r.int64())
+ }
switch b := typ.Underlying().(*types2.Basic); b.Info() & types2.IsConstType {
case types2.IsBoolean:
// Current indexed export format version. Increase with each format change.
// 0: Go1.11 encoding
// 1: added column details to Pos
-// 2: added information for generic function/types (currently unstable)
+// 2: added information for generic function/types. The export of non-generic
+// functions/types remains largely backward-compatible. Breaking changes include:
+// - a 'kind' byte is added to constant values
const (
- iexportVersionGo1_11 = 0
- iexportVersionPosCol = 1
- // TODO: before release, change this back to 2. Kept at previous version
- // for now (for testing).
- iexportVersionGenerics = iexportVersionPosCol
+ iexportVersionGo1_11 = 0
+ iexportVersionPosCol = 1
+ iexportVersionGenerics = 1 // probably change to 2 before release
+ iexportVersionGo1_18 = 2
- iexportVersionCurrent = iexportVersionGenerics
+ iexportVersionCurrent = 2
)
// predeclReserved is the number of type offsets reserved for types
// A typeparam has a name, and has a type bound rather
// than an underlying type.
w.pos(n.Pos())
+ if iexportVersionCurrent >= iexportVersionGo1_18 {
+ implicit := n.Type().Bound().IsImplicit()
+ w.bool(implicit)
+ }
w.typ(n.Type().Bound())
break
}
func (w *exportWriter) value(typ *types.Type, v constant.Value) {
w.typ(typ)
+
+ if iexportVersionCurrent >= iexportVersionGo1_18 {
+ w.int64(int64(v.Kind()))
+ }
+
var kind constant.Kind
var valType *types.Type
if typ.IsTypeParam() {
- // A constant will have a TYPEPARAM type if it appears in a place
- // where it must match that typeparam type (e.g. in a binary
- // operation with a variable of that typeparam type). If so, then
- // we must write out its actual constant kind as well, so its
- // constant val can be read in properly during import.
kind = v.Kind()
- w.int64(int64(kind))
+ if iexportVersionCurrent < iexportVersionGo1_18 {
+ // A constant will have a TYPEPARAM type if it appears in a place
+ // where it must match that typeparam type (e.g. in a binary
+ // operation with a variable of that typeparam type). If so, then
+ // we must write out its actual constant kind as well, so its
+ // constant val can be read in properly during import.
+ w.int64(int64(kind))
+ }
switch kind {
case constant.Int:
version := ird.uint64()
switch version {
- case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
+ case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default:
- if version > iexportVersionGenerics {
- base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version)
- } else {
- base.Errorf("import %q: unknown export format version %d", pkg.Path, version)
- }
+ base.Errorf("import %q: unknown export format version %d", pkg.Path, version)
base.ErrorExit()
}
sym.Def = nname
nname.SetType(t)
t.SetNod(nname)
-
- t.SetBound(r.typ())
+ implicit := false
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ implicit = r.bool()
+ }
+ bound := r.typ()
+ if implicit {
+ bound.MarkImplicit()
+ }
+ t.SetBound(bound)
return nname
case 'V':
var kind constant.Kind
var valType *types.Type
- if typ.IsTypeParam() {
- // If a constant had a typeparam type, then we wrote out its
- // actual constant kind as well.
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ // TODO: add support for using the kind in the non-typeparam case.
kind = constant.Kind(r.int64())
+ }
+
+ if typ.IsTypeParam() {
+ if r.p.exportVersion < iexportVersionGo1_18 {
+ // If a constant had a typeparam type, then we wrote out its
+ // actual constant kind as well.
+ kind = constant.Kind(r.int64())
+ }
switch kind {
case constant.Int:
valType = types.Types[types.TINT64]
}
}
if newfields != nil {
- return types.NewInterface(t.Pkg(), newfields, false)
+ return types.NewInterface(t.Pkg(), newfields, t.IsImplicit())
}
return t
}
return t.extra.(*Interface).implicit
}
+// MarkImplicit marks the interface as implicit.
+func (t *Type) MarkImplicit() {
+ t.wantEtype(TINTER)
+ t.extra.(*Interface).implicit = true
+}
+
// NewUnion returns a new union with the specified set of terms (types). If
// tildes[i] is true, then terms[i] represents ~T, rather than just T.
func NewUnion(terms []*Type, tildes []bool) *Type {
// Keep this in sync with constants in iexport.go.
const (
- iexportVersionGo1_11 = 0
- iexportVersionPosCol = 1
- // TODO: before release, change this back to 2.
- iexportVersionGenerics = iexportVersionPosCol
+ iexportVersionGo1_11 = 0
+ iexportVersionPosCol = 1
+ iexportVersionGenerics = 1 // probably change to 2 before release
+ iexportVersionGo1_18 = 2
- iexportVersionCurrent = iexportVersionGenerics
+ iexportVersionCurrent = 2
)
type ident struct {
version = int64(r.uint64())
switch version {
- case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
+ case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
default:
- if version > iexportVersionGenerics {
- errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
- } else {
- errorf("unknown iexport format version %d", version)
- }
+ errorf("unknown iexport format version %d", version)
}
sLen := int64(r.uint64())
id := ident{r.currPkg.Name(), name}
r.p.tparamIndex[id] = t
- t.SetConstraint(r.typ())
+ var implicit bool
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ implicit = r.bool()
+ }
+ constraint := r.typ()
+ if implicit {
+ iface, _ := constraint.(*types.Interface)
+ if iface == nil {
+ errorf("non-interface constraint marked implicit")
+ }
+ iface.MarkImplicit()
+ }
+ t.SetConstraint(constraint)
case 'V':
typ := r.typ()
func (r *importReader) value() (typ types.Type, val constant.Value) {
typ = r.typ()
+ if r.p.exportVersion >= iexportVersionGo1_18 {
+ // TODO: add support for using the kind
+ _ = constant.Kind(r.int64())
+ }
switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
case types.IsBoolean: