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) { ...@@ -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 { ...@@ -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 ( ...@@ -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) { ...@@ -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 n.Type = nil
return n return n
}
t = types.NewDDDArray(r.Type)
} 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) { ...@@ -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) { ...@@ -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) { ...@@ -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))
n.Left = nil
// Ensure l.Type gets dowidth'd for the backend. Issue 20174. // 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) checkwidth(l.Type)
}
n.Left = nil
break break
} }
...@@ -1257,7 +1247,7 @@ func typecheck1(n *Node, top int) (res *Node) { ...@@ -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) { ...@@ -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) { ...@@ -2796,12 +2802,7 @@ func typecheckcomplit(n *Node) (res *Node) {
n.Type = nil n.Type = nil
case TARRAY: 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()) 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) { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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
......
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