mirror of
https://github.com/golang/go
synced 2024-11-26 03:27:58 -07:00
[dev.regabi] cmd/compile: add NewNamed
The start of abstracting away Type fields. This adds a new constructor for named types, styled after go/types.NewNamed. Along with helper methods for SetNod and Pos, this allows hiding Nod. Change-Id: Ica107034b6346c7b523bf6ae2a34009e350a9aa8 Reviewed-on: https://go-review.googlesource.com/c/go/+/274434 Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
63a6f08b39
commit
f37aa5e4e2
@ -130,6 +130,7 @@ var knownFormats = map[string]string{
|
|||||||
"cmd/compile/internal/types.EType %d": "",
|
"cmd/compile/internal/types.EType %d": "",
|
||||||
"cmd/compile/internal/types.EType %s": "",
|
"cmd/compile/internal/types.EType %s": "",
|
||||||
"cmd/compile/internal/types.EType %v": "",
|
"cmd/compile/internal/types.EType %v": "",
|
||||||
|
"cmd/compile/internal/types.IRNode %v": "",
|
||||||
"cmd/internal/obj.ABI %v": "",
|
"cmd/internal/obj.ABI %v": "",
|
||||||
"error %v": "",
|
"error %v": "",
|
||||||
"float64 %.2f": "",
|
"float64 %.2f": "",
|
||||||
|
@ -205,7 +205,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*path = append(*path, t)
|
*path = append(*path, t)
|
||||||
if findTypeLoop(ir.AsNode(t.Nod).Name().Ntype.Type(), path) {
|
if findTypeLoop(t.Obj().(*ir.Name).Ntype.Type(), path) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
*path = (*path)[:len(*path)-1]
|
*path = (*path)[:len(*path)-1]
|
||||||
@ -314,8 +314,8 @@ func dowidth(t *types.Type) {
|
|||||||
defercheckwidth()
|
defercheckwidth()
|
||||||
|
|
||||||
lno := base.Pos
|
lno := base.Pos
|
||||||
if ir.AsNode(t.Nod) != nil {
|
if pos := t.Pos(); pos.IsKnown() {
|
||||||
base.Pos = ir.AsNode(t.Nod).Pos()
|
base.Pos = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Width = -2
|
t.Width = -2
|
||||||
|
@ -101,9 +101,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) ir.Node {
|
|||||||
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
||||||
n := importsym(ipkg, s, ir.OTYPE)
|
n := importsym(ipkg, s, ir.OTYPE)
|
||||||
if n.Op() != ir.OTYPE {
|
if n.Op() != ir.OTYPE {
|
||||||
t := types.New(types.TFORW)
|
t := types.NewNamed(n)
|
||||||
t.Sym = s
|
|
||||||
t.Nod = n
|
|
||||||
|
|
||||||
n.SetOp(ir.OTYPE)
|
n.SetOp(ir.OTYPE)
|
||||||
n.SetPos(pos)
|
n.SetPos(pos)
|
||||||
|
@ -640,7 +640,7 @@ func (w *exportWriter) doTyp(t *types.Type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.startType(definedType)
|
w.startType(definedType)
|
||||||
w.qualifiedIdent(ir.TypeNode(t))
|
w.qualifiedIdent(t.Obj().(*ir.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ func (r *importReader) doDecl(n ir.Node) {
|
|||||||
// after the underlying type has been assigned.
|
// after the underlying type has been assigned.
|
||||||
defercheckwidth()
|
defercheckwidth()
|
||||||
underlying := r.typ()
|
underlying := r.typ()
|
||||||
types.SetUnderlying(t, underlying)
|
t.SetUnderlying(underlying)
|
||||||
resumecheckwidth()
|
resumecheckwidth()
|
||||||
|
|
||||||
if underlying.IsInterface() {
|
if underlying.IsInterface() {
|
||||||
|
@ -1490,9 +1490,9 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node {
|
|||||||
// typePos returns the position associated with t.
|
// typePos returns the position associated with t.
|
||||||
// This is where t was declared or where it appeared as a type expression.
|
// This is where t was declared or where it appeared as a type expression.
|
||||||
func typePos(t *types.Type) src.XPos {
|
func typePos(t *types.Type) src.XPos {
|
||||||
n := ir.AsNode(t.Nod)
|
if pos := t.Pos(); pos.IsKnown() {
|
||||||
if n == nil || !n.Pos().IsKnown() {
|
return pos
|
||||||
base.Fatalf("bad type: %v", t)
|
|
||||||
}
|
}
|
||||||
return n.Pos()
|
base.Fatalf("bad type: %v", t)
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
@ -3432,10 +3432,8 @@ func typecheckdeftype(n *ir.Name) {
|
|||||||
defer tracePrint("typecheckdeftype", n)(nil)
|
defer tracePrint("typecheckdeftype", n)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
t := types.New(types.TFORW)
|
t := types.NewNamed(n)
|
||||||
t.Sym = n.Sym()
|
|
||||||
t.Vargen = n.Vargen
|
t.Vargen = n.Vargen
|
||||||
t.Nod = n
|
|
||||||
if n.Pragma()&ir.NotInHeap != 0 {
|
if n.Pragma()&ir.NotInHeap != 0 {
|
||||||
t.SetNotInHeap(true)
|
t.SetNotInHeap(true)
|
||||||
}
|
}
|
||||||
@ -3448,7 +3446,7 @@ func typecheckdeftype(n *ir.Name) {
|
|||||||
errorsBefore := base.Errors()
|
errorsBefore := base.Errors()
|
||||||
n.Ntype = typecheckNtype(n.Ntype)
|
n.Ntype = typecheckNtype(n.Ntype)
|
||||||
if underlying := n.Ntype.Type(); underlying != nil {
|
if underlying := n.Ntype.Type(); underlying != nil {
|
||||||
types.SetUnderlying(t, underlying)
|
t.SetUnderlying(underlying)
|
||||||
} else {
|
} else {
|
||||||
n.SetDiag(true)
|
n.SetDiag(true)
|
||||||
n.SetType(nil)
|
n.SetType(nil)
|
||||||
@ -3895,14 +3893,6 @@ func deadcodeexpr(n ir.Node) ir.Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func toTypeNode(orig ir.Node, t *types.Type) ir.Node {
|
|
||||||
n := ir.Nod(ir.OTYPE, nil, nil)
|
|
||||||
n.SetPos(orig.Pos())
|
|
||||||
n.SetType(t)
|
|
||||||
t.Nod = n
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// getIotaValue returns the current value for "iota",
|
// getIotaValue returns the current value for "iota",
|
||||||
// or -1 if not within a ConstSpec.
|
// or -1 if not within a ConstSpec.
|
||||||
func getIotaValue() int64 {
|
func getIotaValue() int64 {
|
||||||
|
@ -337,11 +337,12 @@ func makeErrorInterface() *types.Type {
|
|||||||
|
|
||||||
func lexinit1() {
|
func lexinit1() {
|
||||||
// error type
|
// error type
|
||||||
s := ir.BuiltinPkg.Lookup("error")
|
n := ir.NewNameAt(src.NoXPos, ir.BuiltinPkg.Lookup("error"))
|
||||||
types.Errortype = makeErrorInterface()
|
types.Errortype = types.NewNamed(n)
|
||||||
types.Errortype.Sym = s
|
types.Errortype.SetUnderlying(makeErrorInterface())
|
||||||
types.Errortype.Orig = makeErrorInterface()
|
n.SetOp(ir.OTYPE)
|
||||||
s.Def = ir.TypeNode(types.Errortype)
|
n.SetType(types.Errortype)
|
||||||
|
n.Sym().Def = n
|
||||||
dowidth(types.Errortype)
|
dowidth(types.Errortype)
|
||||||
|
|
||||||
// We create separate byte and rune types for better error messages
|
// We create separate byte and rune types for better error messages
|
||||||
@ -353,7 +354,7 @@ func lexinit1() {
|
|||||||
// type aliases, albeit at the cost of having to deal with it everywhere).
|
// type aliases, albeit at the cost of having to deal with it everywhere).
|
||||||
|
|
||||||
// byte alias
|
// byte alias
|
||||||
s = ir.BuiltinPkg.Lookup("byte")
|
s := ir.BuiltinPkg.Lookup("byte")
|
||||||
types.Bytetype = types.New(types.TUINT8)
|
types.Bytetype = types.New(types.TUINT8)
|
||||||
types.Bytetype.Sym = s
|
types.Bytetype.Sym = s
|
||||||
s.Def = ir.TypeNode(types.Bytetype)
|
s.Def = ir.TypeNode(types.Bytetype)
|
||||||
|
@ -545,9 +545,7 @@ func (*ParenExpr) CanBeNtype() {}
|
|||||||
func (n *ParenExpr) SetOTYPE(t *types.Type) {
|
func (n *ParenExpr) SetOTYPE(t *types.Type) {
|
||||||
n.op = OTYPE
|
n.op = OTYPE
|
||||||
n.typ = t
|
n.typ = t
|
||||||
if t.Nod == nil {
|
t.SetNod(n)
|
||||||
t.Nod = n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ResultExpr represents a direct access to a result slot on the stack frame.
|
// A ResultExpr represents a direct access to a result slot on the stack frame.
|
||||||
@ -762,9 +760,7 @@ func (n *StarExpr) SetOTYPE(t *types.Type) {
|
|||||||
n.op = OTYPE
|
n.op = OTYPE
|
||||||
n.X = nil
|
n.X = nil
|
||||||
n.typ = t
|
n.typ = t
|
||||||
if t.Nod == nil {
|
t.SetNod(n)
|
||||||
t.Nod = n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *StarExpr) DeepCopy(pos src.XPos) Node {
|
func (n *StarExpr) DeepCopy(pos src.XPos) Node {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package ir
|
package ir
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -51,12 +52,7 @@ func (n *miniType) setOTYPE(t *types.Type, self Node) {
|
|||||||
}
|
}
|
||||||
n.op = OTYPE
|
n.op = OTYPE
|
||||||
n.typ = t
|
n.typ = t
|
||||||
|
t.SetNod(self)
|
||||||
// t.Nod can be non-nil already
|
|
||||||
// in the case of shared *type.Types, like []byte or interface{}.
|
|
||||||
if t.Nod == nil {
|
|
||||||
t.Nod = self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE
|
func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE
|
||||||
@ -362,20 +358,11 @@ func (n *typeNode) CanBeNtype() {}
|
|||||||
|
|
||||||
// TypeNode returns the Node representing the type t.
|
// TypeNode returns the Node representing the type t.
|
||||||
func TypeNode(t *types.Type) Ntype {
|
func TypeNode(t *types.Type) Ntype {
|
||||||
return TypeNodeAt(src.NoXPos, t)
|
if n := t.Obj(); n != nil {
|
||||||
}
|
if n.Type() != t {
|
||||||
|
base.Fatalf("type skew: %v has type %v, but expected %v", n, n.Type(), t)
|
||||||
// TypeNodeAt returns the Node representing the type t.
|
}
|
||||||
// If the node must be created, TypeNodeAt uses the position pos.
|
return n.(Ntype)
|
||||||
// TODO(rsc): Does anyone actually use position on these type nodes?
|
|
||||||
func TypeNodeAt(pos src.XPos, t *types.Type) Ntype {
|
|
||||||
// If we copied another type with *t = *u,
|
|
||||||
// then t.Nod might be out of date, so check t.Nod.Type() too.
|
|
||||||
n := AsNode(t.Nod)
|
|
||||||
if n == nil || n.Type() != t {
|
|
||||||
n := newTypeNode(pos, t) // t.Sym may be nil
|
|
||||||
t.Nod = n
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
return n.(Ntype)
|
return newTypeNode(src.NoXPos, t)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,11 @@ import (
|
|||||||
// IRNode represents an ir.Node, but without needing to import cmd/compile/internal/ir,
|
// IRNode represents an ir.Node, but without needing to import cmd/compile/internal/ir,
|
||||||
// which would cause an import cycle. The uses in other packages must type assert
|
// which would cause an import cycle. The uses in other packages must type assert
|
||||||
// values of type IRNode to ir.Node or a more specific type.
|
// values of type IRNode to ir.Node or a more specific type.
|
||||||
type IRNode interface{ Type() *Type }
|
type IRNode interface {
|
||||||
|
Pos() src.XPos
|
||||||
|
Sym() *Sym
|
||||||
|
Type() *Type
|
||||||
|
}
|
||||||
|
|
||||||
//go:generate stringer -type EType -trimprefix T
|
//go:generate stringer -type EType -trimprefix T
|
||||||
|
|
||||||
@ -142,7 +146,7 @@ type Type struct {
|
|||||||
methods Fields
|
methods Fields
|
||||||
allMethods Fields
|
allMethods Fields
|
||||||
|
|
||||||
Nod IRNode // canonical OTYPE node
|
nod IRNode // canonical OTYPE node
|
||||||
Orig *Type // original type (type literal or predefined type)
|
Orig *Type // original type (type literal or predefined type)
|
||||||
|
|
||||||
// Cache of composite types, with this type being the element type.
|
// Cache of composite types, with this type being the element type.
|
||||||
@ -180,6 +184,24 @@ func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) }
|
|||||||
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
|
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
|
||||||
func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
|
func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
|
||||||
|
|
||||||
|
// SetNod associates t with syntax node n.
|
||||||
|
func (t *Type) SetNod(n IRNode) {
|
||||||
|
// t.nod can be non-nil already
|
||||||
|
// in the case of shared *Types, like []byte or interface{}.
|
||||||
|
if t.nod == nil {
|
||||||
|
t.nod = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pos returns a position associated with t, if any.
|
||||||
|
// This should only be used for diagnostics.
|
||||||
|
func (t *Type) Pos() src.XPos {
|
||||||
|
if t.nod != nil {
|
||||||
|
return t.nod.Pos()
|
||||||
|
}
|
||||||
|
return src.NoXPos
|
||||||
|
}
|
||||||
|
|
||||||
// Pkg returns the package that t appeared in.
|
// Pkg returns the package that t appeared in.
|
||||||
//
|
//
|
||||||
// Pkg is only defined for function, struct, and interface types
|
// Pkg is only defined for function, struct, and interface types
|
||||||
@ -1519,7 +1541,24 @@ var (
|
|||||||
TypeInt128 = newSSA("int128")
|
TypeInt128 = newSSA("int128")
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetUnderlying(t, underlying *Type) {
|
// NewNamed returns a new named type for the given type name.
|
||||||
|
func NewNamed(obj IRNode) *Type {
|
||||||
|
t := New(TFORW)
|
||||||
|
t.Sym = obj.Sym()
|
||||||
|
t.nod = obj
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obj returns the type name for the named type t.
|
||||||
|
func (t *Type) Obj() IRNode {
|
||||||
|
if t.Sym != nil {
|
||||||
|
return t.nod
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUnderlying sets the underlying type.
|
||||||
|
func (t *Type) SetUnderlying(underlying *Type) {
|
||||||
if underlying.Etype == TFORW {
|
if underlying.Etype == TFORW {
|
||||||
// This type isn't computed yet; when it is, update n.
|
// This type isn't computed yet; when it is, update n.
|
||||||
underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
|
underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
|
||||||
@ -1546,13 +1585,13 @@ func SetUnderlying(t, underlying *Type) {
|
|||||||
// to the existing type, but the method set of an interface
|
// to the existing type, but the method set of an interface
|
||||||
// type [...] remains unchanged."
|
// type [...] remains unchanged."
|
||||||
if t.IsInterface() {
|
if t.IsInterface() {
|
||||||
*t.Methods() = *underlying.Methods()
|
t.methods = underlying.methods
|
||||||
*t.AllMethods() = *underlying.AllMethods()
|
t.allMethods = underlying.allMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update types waiting on this type.
|
// Update types waiting on this type.
|
||||||
for _, w := range ft.Copyto {
|
for _, w := range ft.Copyto {
|
||||||
SetUnderlying(w, t)
|
w.SetUnderlying(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double-check use of type as embedded type.
|
// Double-check use of type as embedded type.
|
||||||
|
Loading…
Reference in New Issue
Block a user