mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: remove DDD array types
Currently we handle [...]T array literals by treating [...]T as special "DDD array" types. However, these array literals are just composite literal syntax, not a distinct Go type. Moreover, representing them as Go types contributes to complexity in a number of unrelated bits of code. This CL changes OCOMPLIT typechecking to look for the [...]T syntax and handle it specially, so we can remove DDD arrays. Passes toolstash-check. Change-Id: Ibbf701eac4caa7a321e2d10e256658fdfaa8a160 Reviewed-on: https://go-review.googlesource.com/c/go/+/197604 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
e1b1b7856f
commit
616c39f6a6
4 changed files with 33 additions and 78 deletions
|
|
@ -324,13 +324,6 @@ func dowidth(t *types.Type) {
|
||||||
if t.Elem() == nil {
|
if t.Elem() == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if t.IsDDDArray() {
|
|
||||||
if !t.Broke() {
|
|
||||||
yyerror("use of [...] array outside of array literal")
|
|
||||||
t.SetBroke(true)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
dowidth(t.Elem())
|
dowidth(t.Elem())
|
||||||
if t.Elem().Width != 0 {
|
if t.Elem().Width != 0 {
|
||||||
|
|
|
||||||
|
|
@ -720,9 +720,6 @@ func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
|
||||||
return "*" + tmodeString(t.Elem(), mode, depth)
|
return "*" + tmodeString(t.Elem(), mode, depth)
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
if t.IsDDDArray() {
|
|
||||||
return "[...]" + tmodeString(t.Elem(), mode, depth)
|
|
||||||
}
|
|
||||||
return "[" + strconv.FormatInt(t.NumElem(), 10) + "]" + tmodeString(t.Elem(), mode, depth)
|
return "[" + strconv.FormatInt(t.NumElem(), 10) + "]" + tmodeString(t.Elem(), mode, depth)
|
||||||
|
|
||||||
case TSLICE:
|
case TSLICE:
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ const (
|
||||||
ctxCallee // call-only expressions are ok
|
ctxCallee // call-only expressions are ok
|
||||||
ctxMultiOK // multivalue function returns are ok
|
ctxMultiOK // multivalue function returns are ok
|
||||||
ctxAssign // assigning to expression
|
ctxAssign // assigning to expression
|
||||||
ctxCompLit // type in composite literal
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// type checks the whole tree of an expression.
|
// type checks the whole tree of an expression.
|
||||||
|
|
@ -413,15 +412,12 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
if n.Left == nil {
|
if n.Left == nil {
|
||||||
t = types.NewSlice(r.Type)
|
t = types.NewSlice(r.Type)
|
||||||
} else if n.Left.Op == ODDD {
|
} else if n.Left.Op == ODDD {
|
||||||
if top&ctxCompLit == 0 {
|
if !n.Diag() {
|
||||||
if !n.Diag() {
|
n.SetDiag(true)
|
||||||
n.SetDiag(true)
|
yyerror("use of [...] array outside of array literal")
|
||||||
yyerror("use of [...] array outside of array literal")
|
|
||||||
}
|
|
||||||
n.Type = nil
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
t = types.NewDDDArray(r.Type)
|
n.Type = nil
|
||||||
|
return n
|
||||||
} else {
|
} else {
|
||||||
n.Left = indexlit(typecheck(n.Left, ctxExpr))
|
n.Left = indexlit(typecheck(n.Left, ctxExpr))
|
||||||
l := n.Left
|
l := n.Left
|
||||||
|
|
@ -457,9 +453,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
setTypeNode(n, t)
|
setTypeNode(n, t)
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
if !t.IsDDDArray() {
|
checkwidth(t)
|
||||||
checkwidth(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
case OTMAP:
|
case OTMAP:
|
||||||
ok |= ctxType
|
ok |= ctxType
|
||||||
|
|
@ -517,7 +511,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
|
|
||||||
// type or expr
|
// type or expr
|
||||||
case ODEREF:
|
case ODEREF:
|
||||||
n.Left = typecheck(n.Left, ctxExpr|ctxType|top&ctxCompLit)
|
n.Left = typecheck(n.Left, ctxExpr|ctxType)
|
||||||
l := n.Left
|
l := n.Left
|
||||||
t := l.Type
|
t := l.Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
|
|
@ -527,13 +521,9 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
if l.Op == OTYPE {
|
if l.Op == OTYPE {
|
||||||
ok |= ctxType
|
ok |= ctxType
|
||||||
setTypeNode(n, types.NewPtr(l.Type))
|
setTypeNode(n, types.NewPtr(l.Type))
|
||||||
// Ensure l.Type gets dowidth'd for the backend. Issue 20174.
|
|
||||||
// Don't checkwidth [...] arrays, though, since they
|
|
||||||
// will be replaced by concrete-sized arrays. Issue 20333.
|
|
||||||
if !l.Type.IsDDDArray() {
|
|
||||||
checkwidth(l.Type)
|
|
||||||
}
|
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
|
// Ensure l.Type gets dowidth'd for the backend. Issue 20174.
|
||||||
|
checkwidth(l.Type)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1257,7 +1247,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
n.Left = defaultlit(n.Left, nil)
|
n.Left = defaultlit(n.Left, nil)
|
||||||
l = n.Left
|
l = n.Left
|
||||||
if l.Op == OTYPE {
|
if l.Op == OTYPE {
|
||||||
if n.IsDDD() || l.Type.IsDDDArray() {
|
if n.IsDDD() {
|
||||||
if !l.Type.Broke() {
|
if !l.Type.Broke() {
|
||||||
yyerror("invalid use of ... in type conversion to %v", l.Type)
|
yyerror("invalid use of ... in type conversion to %v", l.Type)
|
||||||
}
|
}
|
||||||
|
|
@ -2777,17 +2767,33 @@ func typecheckcomplit(n *Node) (res *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save original node (including n.Right)
|
// Save original node (including n.Right)
|
||||||
norig := n.copy()
|
n.Orig = n.copy()
|
||||||
|
|
||||||
setlineno(n.Right)
|
setlineno(n.Right)
|
||||||
n.Right = typecheck(n.Right, ctxType|ctxCompLit)
|
|
||||||
l := n.Right // sic
|
// Need to handle [...]T arrays specially.
|
||||||
t := l.Type
|
if n.Right.Op == OTARRAY && n.Right.Left != nil && n.Right.Left.Op == ODDD {
|
||||||
|
n.Right.Right = typecheck(n.Right.Right, ctxType)
|
||||||
|
if n.Right.Right.Type == nil {
|
||||||
|
n.Type = nil
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
elemType := n.Right.Right.Type
|
||||||
|
|
||||||
|
length := typecheckarraylit(elemType, -1, n.List.Slice())
|
||||||
|
|
||||||
|
n.Op = OARRAYLIT
|
||||||
|
n.Type = types.NewArray(elemType, length)
|
||||||
|
n.Right = nil
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Right = typecheck(n.Right, ctxType)
|
||||||
|
t := n.Right.Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
nerr := nerrors
|
|
||||||
n.Type = t
|
n.Type = t
|
||||||
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
|
|
@ -2796,12 +2802,7 @@ func typecheckcomplit(n *Node) (res *Node) {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
if t.IsDDDArray() {
|
typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
|
||||||
length := typecheckarraylit(t.Elem(), -1, n.List.Slice())
|
|
||||||
t.SetNumElem(length)
|
|
||||||
} else {
|
|
||||||
typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
|
|
||||||
}
|
|
||||||
n.Op = OARRAYLIT
|
n.Op = OARRAYLIT
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
|
|
||||||
|
|
@ -2954,11 +2955,6 @@ func typecheckcomplit(n *Node) (res *Node) {
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if nerr != nerrors {
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Orig = norig
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -495,14 +495,6 @@ func NewSlice(elem *Type) *Type {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDDDArray returns a new [...]T array Type.
|
|
||||||
func NewDDDArray(elem *Type) *Type {
|
|
||||||
t := New(TARRAY)
|
|
||||||
t.Extra = &Array{Elem: elem, Bound: -1}
|
|
||||||
t.SetNotInHeap(elem.NotInHeap())
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewChan returns a new chan Type with direction dir.
|
// NewChan returns a new chan Type with direction dir.
|
||||||
func NewChan(elem *Type, dir ChanDir) *Type {
|
func NewChan(elem *Type, dir ChanDir) *Type {
|
||||||
t := New(TCHAN)
|
t := New(TCHAN)
|
||||||
|
|
@ -882,13 +874,6 @@ func (t *Type) SetInterface(methods []*Field) {
|
||||||
t.Methods().Set(methods)
|
t.Methods().Set(methods)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) IsDDDArray() bool {
|
|
||||||
if t.Etype != TARRAY {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return t.Extra.(*Array).Bound < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Type) WidthCalculated() bool {
|
func (t *Type) WidthCalculated() bool {
|
||||||
return t.Align > 0
|
return t.Align > 0
|
||||||
}
|
}
|
||||||
|
|
@ -1325,23 +1310,7 @@ func (t *Type) FieldName(i int) string {
|
||||||
|
|
||||||
func (t *Type) NumElem() int64 {
|
func (t *Type) NumElem() int64 {
|
||||||
t.wantEtype(TARRAY)
|
t.wantEtype(TARRAY)
|
||||||
at := t.Extra.(*Array)
|
return t.Extra.(*Array).Bound
|
||||||
if at.Bound < 0 {
|
|
||||||
Fatalf("NumElem array %v does not have bound yet", t)
|
|
||||||
}
|
|
||||||
return at.Bound
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNumElem sets the number of elements in an array type.
|
|
||||||
// The only allowed use is on array types created with NewDDDArray.
|
|
||||||
// For other uses, create a new array with NewArray instead.
|
|
||||||
func (t *Type) SetNumElem(n int64) {
|
|
||||||
t.wantEtype(TARRAY)
|
|
||||||
at := t.Extra.(*Array)
|
|
||||||
if at.Bound >= 0 {
|
|
||||||
Fatalf("SetNumElem array %v already has bound %d", t, at.Bound)
|
|
||||||
}
|
|
||||||
at.Bound = n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type componentsIncludeBlankFields bool
|
type componentsIncludeBlankFields bool
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue