diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 989805c1df43c59e3029b58aec4062332545bfa0..b13f2e2e1caaabe0b0d597c882b0ead9f74cc445 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2795,75 +2795,20 @@ func typecheckcomplit(n *Node) (res *Node) {
 		yyerror("invalid composite literal type %v", t)
 		n.Type = nil
 
-	case TARRAY, TSLICE:
-		// If there are key/value pairs, create a map to keep seen
-		// keys so we can check for duplicate indices.
-		var indices map[int64]bool
-		for _, n1 := range n.List.Slice() {
-			if n1.Op == OKEY {
-				indices = make(map[int64]bool)
-				break
-			}
-		}
-
-		var length, i int64
-		checkBounds := t.IsArray() && !t.IsDDDArray()
-		nl := n.List.Slice()
-		for i2, l := range nl {
-			setlineno(l)
-			vp := &nl[i2]
-			if l.Op == OKEY {
-				l.Left = typecheck(l.Left, ctxExpr)
-				evconst(l.Left)
-				i = indexconst(l.Left)
-				if i < 0 {
-					if !l.Left.Diag() {
-						if i == -2 {
-							yyerror("index too large")
-						} else {
-							yyerror("index must be non-negative integer constant")
-						}
-						l.Left.SetDiag(true)
-					}
-					i = -(1 << 30) // stay negative for a while
-				}
-				vp = &l.Right
-			}
-
-			if i >= 0 && indices != nil {
-				if indices[i] {
-					yyerror("duplicate index in array literal: %d", i)
-				} else {
-					indices[i] = true
-				}
-			}
-
-			r := *vp
-			r = pushtype(r, t.Elem())
-			r = typecheck(r, ctxExpr)
-			*vp = assignconv(r, t.Elem(), "array or slice literal")
-
-			i++
-			if i > length {
-				length = i
-				if checkBounds && length > t.NumElem() {
-					setlineno(l)
-					yyerror("array index %d out of bounds [0:%d]", length-1, t.NumElem())
-					checkBounds = false
-				}
-			}
-		}
-
+	case TARRAY:
 		if t.IsDDDArray() {
+			length := typecheckarraylit(t.Elem(), -1, n.List.Slice())
 			t.SetNumElem(length)
-		}
-		if t.IsSlice() {
-			n.Op = OSLICELIT
-			n.Right = nodintconst(length)
 		} else {
-			n.Op = OARRAYLIT
-			n.Right = nil
+			typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
 		}
+		n.Op = OARRAYLIT
+		n.Right = nil
+
+	case TSLICE:
+		length := typecheckarraylit(t.Elem(), -1, n.List.Slice())
+		n.Op = OSLICELIT
+		n.Right = nodintconst(length)
 
 	case TMAP:
 		var cs constSet
@@ -3017,6 +2962,67 @@ func typecheckcomplit(n *Node) (res *Node) {
 	return n
 }
 
+func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node) int64 {
+	// If there are key/value pairs, create a map to keep seen
+	// keys so we can check for duplicate indices.
+	var indices map[int64]bool
+	for _, elt := range elts {
+		if elt.Op == OKEY {
+			indices = make(map[int64]bool)
+			break
+		}
+	}
+
+	var key, length int64
+	for i, elt := range elts {
+		setlineno(elt)
+		vp := &elts[i]
+		if elt.Op == OKEY {
+			elt.Left = typecheck(elt.Left, ctxExpr)
+			key = indexconst(elt.Left)
+			if key < 0 {
+				if !elt.Left.Diag() {
+					if key == -2 {
+						yyerror("index too large")
+					} else {
+						yyerror("index must be non-negative integer constant")
+					}
+					elt.Left.SetDiag(true)
+				}
+				key = -(1 << 30) // stay negative for a while
+			}
+			vp = &elt.Right
+		}
+
+		r := *vp
+		r = pushtype(r, elemType)
+		r = typecheck(r, ctxExpr)
+		*vp = assignconv(r, elemType, "array or slice literal")
+
+		if key >= 0 {
+			if indices != nil {
+				if indices[key] {
+					yyerror("duplicate index in array literal: %d", key)
+				} else {
+					indices[key] = true
+				}
+			}
+
+			if bound >= 0 && key >= bound {
+				yyerror("array index %d out of bounds [0:%d]", key, bound)
+				bound = -1
+			}
+		}
+
+		key++
+		if key > length {
+			length = key
+		}
+	}
+
+	return length
+}
+
 // visible reports whether sym is exported or locally defined.
 func visible(sym *types.Sym) bool {
 	return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == localpkg)