diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index b23dd476008..54a13b498b9 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -154,8 +154,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { name, obj := g.def(decl.Name) ntyp, otyp := name.Type(), obj.Type() if ir.CurFunc != nil { - typecheck.TypeGen++ - ntyp.Vargen = typecheck.TypeGen + ntyp.SetVargen() } pragmas := g.pragmaFlags(decl.Pragma, typePragmas) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index db1b11c4cfd..404af5b1b2c 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -1736,11 +1736,6 @@ func CheckMapKeys() { mapqueue = nil } -// TypeGen tracks the number of function-scoped defined types that -// have been declared. It's used to generate unique linker symbols for -// their runtime type descriptors. -var TypeGen int32 - func typecheckdeftype(n *ir.Name) { if base.EnableTrace && base.Flag.LowerT { defer tracePrint("typecheckdeftype", n)(nil) @@ -1748,8 +1743,7 @@ func typecheckdeftype(n *ir.Name) { t := types.NewNamed(n) if n.Curfn != nil { - TypeGen++ - t.Vargen = TypeGen + t.SetVargen() } if n.Pragma()&ir.NotInHeap != 0 { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b1b85064007..74ebfad5bb9 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -361,8 +361,8 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type // output too. It seems like it should, but that mode is currently // used in string representation used by reflection, which is // user-visible and doesn't expect this. - if mode == fmtTypeID && t.Vargen != 0 { - fmt.Fprintf(b, "·%d", t.Vargen) + if mode == fmtTypeID && t.vargen != 0 { + fmt.Fprintf(b, "·%d", t.vargen) } return } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 975280753a4..06348c50946 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -178,7 +178,7 @@ type Type struct { } sym *Sym // symbol containing name, for named types - Vargen int32 // unique name for OTYPE/ONAME + vargen int32 // unique name for OTYPE/ONAME kind Kind // kind of type Align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) @@ -1221,8 +1221,8 @@ func (t *Type) cmp(x *Type) Cmp { if x.sym != nil { // Syms non-nil, if vargens match then equal. - if t.Vargen != x.Vargen { - return cmpForNe(t.Vargen < x.Vargen) + if t.vargen != x.vargen { + return cmpForNe(t.vargen < x.vargen) } return CMPeq } @@ -1768,6 +1768,25 @@ func (t *Type) Obj() Object { return nil } +// typeGen tracks the number of function-scoped defined types that +// have been declared. It's used to generate unique linker symbols for +// their runtime type descriptors. +var typeGen int32 + +// SetVargen assigns a unique generation number to type t, which must +// be a defined type declared within function scope. The generation +// number is used to distinguish it from other similarly spelled +// defined types from the same package. +// +// TODO(mdempsky): Come up with a better solution. +func (t *Type) SetVargen() { + base.Assertf(t.Sym() != nil, "SetVargen on anonymous type %v", t) + base.Assertf(t.vargen == 0, "type %v already has Vargen %v", t, t.vargen) + + typeGen++ + t.vargen = typeGen +} + // SetUnderlying sets the underlying type. SetUnderlying automatically updates any // types that were waiting for this type to be completed. func (t *Type) SetUnderlying(underlying *Type) {