Skip to content

Commit

Permalink
cmd/compile: remove DDD array types
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mdempsky committed Sep 26, 2019
1 parent e1b1b78 commit 616c39f
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 78 deletions.
7 changes: 0 additions & 7 deletions src/cmd/compile/internal/gc/align.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 0 additions & 3 deletions src/cmd/compile/internal/gc/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
68 changes: 32 additions & 36 deletions src/cmd/compile/internal/gc/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
if !n.Diag() {
n.SetDiag(true)
yyerror("use of [...] array outside of array literal")
}
t = types.NewDDDArray(r.Type)
n.Type = nil
return n
} else {
n.Left = indexlit(typecheck(n.Left, ctxExpr))
l := n.Left
Expand Down Expand Up @@ -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)
}
checkwidth(t)

case OTMAP:
ok |= ctxType
Expand Down Expand Up @@ -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 {
Expand All @@ -527,13 +521,9 @@ func typecheck1(n *Node, top int) (res *Node) {
if l.Op == OTYPE {
ok |= ctxType
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
// Ensure l.Type gets dowidth'd for the backend. Issue 20174.
checkwidth(l.Type)
break
}

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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())
}
typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
n.Op = OARRAYLIT
n.Right = nil

Expand Down Expand Up @@ -2954,11 +2955,6 @@ func typecheckcomplit(n *Node) (res *Node) {
n.Right = nil
}

if nerr != nerrors {
return n
}

n.Orig = norig
return n
}

Expand Down
33 changes: 1 addition & 32 deletions src/cmd/compile/internal/types/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 616c39f

Please sign in to comment.