Commit 616c39f6 authored by Matthew Dempsky's avatar Matthew Dempsky

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: default avatarRobert Griesemer <gri@golang.org>
parent e1b1b785
......@@ -324,13 +324,6 @@ func dowidth(t *types.Type) {
if t.Elem() == nil {
break
}
if t.IsDDDArray() {
if !t.Broke() {
yyerror("use of [...] array outside of array literal")
t.SetBroke(true)
}
break
}
dowidth(t.Elem())
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)
case TARRAY:
if t.IsDDDArray() {
return "[...]" + tmodeString(t.Elem(), mode, depth)
}
return "[" + strconv.FormatInt(t.NumElem(), 10) + "]" + tmodeString(t.Elem(), mode, depth)
case TSLICE:
......
......@@ -62,7 +62,6 @@ const (
ctxCallee // call-only expressions are ok
ctxMultiOK // multivalue function returns are ok
ctxAssign // assigning to expression
ctxCompLit // type in composite literal
)
// type checks the whole tree of an expression.
......@@ -413,15 +412,12 @@ func typecheck1(n *Node, top int) (res *Node) {
if n.Left == nil {
t = types.NewSlice(r.Type)
} else if n.Left.Op == ODDD {
if top&ctxCompLit == 0 {
if !n.Diag() {
n.SetDiag(true)
yyerror("use of [...] array outside of array literal")
}
n.Type = nil
return n
}
t = types.NewDDDArray(r.Type)
} else {
n.Left = indexlit(typecheck(n.Left, ctxExpr))
l := n.Left
......@@ -457,9 +453,7 @@ func typecheck1(n *Node, top int) (res *Node) {
setTypeNode(n, t)
n.Left = nil
n.Right = nil
if !t.IsDDDArray() {
checkwidth(t)
}
case OTMAP:
ok |= ctxType
......@@ -517,7 +511,7 @@ func typecheck1(n *Node, top int) (res *Node) {
// type or expr
case ODEREF:
n.Left = typecheck(n.Left, ctxExpr|ctxType|top&ctxCompLit)
n.Left = typecheck(n.Left, ctxExpr|ctxType)
l := n.Left
t := l.Type
if t == nil {
......@@ -527,13 +521,9 @@ func typecheck1(n *Node, top int) (res *Node) {
if l.Op == OTYPE {
ok |= ctxType
setTypeNode(n, types.NewPtr(l.Type))
n.Left = nil
// 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
break
}
......@@ -1257,7 +1247,7 @@ func typecheck1(n *Node, top int) (res *Node) {
n.Left = defaultlit(n.Left, nil)
l = n.Left
if l.Op == OTYPE {
if n.IsDDD() || l.Type.IsDDDArray() {
if n.IsDDD() {
if !l.Type.Broke() {
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)
norig := n.copy()
n.Orig = n.copy()
setlineno(n.Right)
n.Right = typecheck(n.Right, ctxType|ctxCompLit)
l := n.Right // sic
t := l.Type
// Need to handle [...]T arrays specially.
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 {
n.Type = nil
return n
}
nerr := nerrors
n.Type = t
switch t.Etype {
......@@ -2796,12 +2802,7 @@ func typecheckcomplit(n *Node) (res *Node) {
n.Type = nil
case TARRAY:
if t.IsDDDArray() {
length := typecheckarraylit(t.Elem(), -1, n.List.Slice())
t.SetNumElem(length)
} else {
typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
}
n.Op = OARRAYLIT
n.Right = nil
......@@ -2954,11 +2955,6 @@ func typecheckcomplit(n *Node) (res *Node) {
n.Right = nil
}
if nerr != nerrors {
return n
}
n.Orig = norig
return n
}
......
......@@ -495,14 +495,6 @@ func NewSlice(elem *Type) *Type {
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.
func NewChan(elem *Type, dir ChanDir) *Type {
t := New(TCHAN)
......@@ -882,13 +874,6 @@ func (t *Type) SetInterface(methods []*Field) {
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 {
return t.Align > 0
}
......@@ -1325,23 +1310,7 @@ func (t *Type) FieldName(i int) string {
func (t *Type) NumElem() int64 {
t.wantEtype(TARRAY)
at := t.Extra.(*Array)
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
return t.Extra.(*Array).Bound
}
type componentsIncludeBlankFields bool
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment