ast::type: Remove Array::set_decorations

Move to constructor

Bug: tint:390
Change-Id: If6c65b7305db7f9977c0cc9884a8f551e07de050
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35014
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/ast/builder.h b/src/ast/builder.h
index 4b441f5..59d3ce2 100644
--- a/src/ast/builder.h
+++ b/src/ast/builder.h
@@ -146,7 +146,7 @@
   /// @param n the array size. 0 represents unbounded
   /// @return the tint AST type for a array of size `n` of type `T`
   type::Array* array(type::Type* subtype, uint32_t n) const {
-    return mod_->create<type::Array>(subtype, n);
+    return mod_->create<type::Array>(subtype, n, ArrayDecorationList{});
   }
 
   /// @return the tint AST type for an array of size `N` of type `T`
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index b49f64c..65e6cfe 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -106,20 +106,16 @@
 
 TEST_F(AccessControlTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array array(&u32, 4);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 4,
+              ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AccessControlTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array array(&u32);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 0,
+              ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(4u, at.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
@@ -153,20 +149,16 @@
 
 TEST_F(AccessControlTest, BaseAlignmentArray) {
   U32 u32;
-  Array array(&u32, 4);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 4,
+              ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AccessControlTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array array(&u32);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 0,
+              ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 7979efa..2c2dc49 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -169,20 +169,20 @@
 
 TEST_F(AliasTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array array(&u32, 4);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 4,
+              ArrayDecorationList{
+                  create<StrideDecoration>(4, Source{}),
+              });
   Alias alias{"alias", &array};
   EXPECT_EQ(16u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AliasTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array array(&u32);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 0,
+              ArrayDecorationList{
+                  create<StrideDecoration>(4, Source{}),
+              });
   Alias alias{"alias", &array};
   EXPECT_EQ(4u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
@@ -218,20 +218,20 @@
 
 TEST_F(AliasTest, BaseAlignmentArray) {
   U32 u32;
-  Array array(&u32, 4);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 4,
+              ArrayDecorationList{
+                  create<StrideDecoration>(4, Source{}),
+              });
   Alias alias{"alias", &array};
   EXPECT_EQ(16u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AliasTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array array(&u32);
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-  array.set_decorations(decos);
+  Array array(&u32, 0,
+              ArrayDecorationList{
+                  create<StrideDecoration>(4, Source{}),
+              });
   Alias alias{"alias", &array};
   EXPECT_EQ(16u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
diff --git a/src/ast/type/array_type.cc b/src/ast/type/array_type.cc
index bc22cf5..be71ad7 100644
--- a/src/ast/type/array_type.cc
+++ b/src/ast/type/array_type.cc
@@ -28,9 +28,8 @@
 namespace ast {
 namespace type {
 
-Array::Array(Type* subtype) : subtype_(subtype) {}
-
-Array::Array(Type* subtype, uint32_t size) : subtype_(subtype), size_(size) {}
+Array::Array(Type* subtype, uint32_t size, ArrayDecorationList decorations)
+    : subtype_(subtype), size_(size), decos_(decorations) {}
 
 Array::Array(Array&&) = default;
 
@@ -98,9 +97,8 @@
 }
 
 Array* Array::Clone(CloneContext* ctx) const {
-  auto cloned = std::make_unique<Array>(ctx->Clone(subtype_), size_);
-  cloned->set_decorations(ctx->Clone(decorations()));
-  return ctx->mod->unique_type(std::move(cloned));
+  return ctx->mod->create<Array>(ctx->Clone(subtype_), size_,
+                                 ctx->Clone(decorations()));
 }
 
 }  // namespace type
diff --git a/src/ast/type/array_type.h b/src/ast/type/array_type.h
index 8c4bc9a..a120a46 100644
--- a/src/ast/type/array_type.h
+++ b/src/ast/type/array_type.h
@@ -30,13 +30,12 @@
 /// An array type. If size is zero then it is a runtime array.
 class Array : public Castable<Array, Type> {
  public:
-  /// Constructor for runtime array
-  /// @param subtype the type of the array elements
-  explicit Array(Type* subtype);
   /// Constructor
   /// @param subtype the type of the array elements
-  /// @param size the number of elements in the array
-  Array(Type* subtype, uint32_t size);
+  /// @param size the number of elements in the array. `0` represents a
+  /// runtime-sized array.
+  /// @param decorations the array decorations
+  Array(Type* subtype, uint32_t size, ArrayDecorationList decorations);
   /// Move constructor
   Array(Array&&);
   ~Array() override;
@@ -55,9 +54,6 @@
   ///          0 for non-host shareable types.
   uint64_t BaseAlignment(MemoryLayout mem_layout) const override;
 
-  /// Sets the array decorations
-  /// @param decos the decorations to set
-  void set_decorations(ArrayDecorationList decos) { decos_ = std::move(decos); }
   /// @returns the array decorations
   const ArrayDecorationList& decorations() const { return decos_; }
 
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 3dbcdda..5d929fa 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -39,7 +39,7 @@
 
 TEST_F(ArrayTest, CreateSizedArray) {
   U32 u32;
-  Array arr{&u32, 3};
+  Array arr{&u32, 3, ArrayDecorationList{}};
   EXPECT_EQ(arr.type(), &u32);
   EXPECT_EQ(arr.size(), 3u);
   EXPECT_TRUE(arr.Is<Array>());
@@ -48,7 +48,7 @@
 
 TEST_F(ArrayTest, CreateRuntimeArray) {
   U32 u32;
-  Array arr{&u32};
+  Array arr{&u32, 0, ArrayDecorationList{}};
   EXPECT_EQ(arr.type(), &u32);
   EXPECT_EQ(arr.size(), 0u);
   EXPECT_TRUE(arr.Is<Array>());
@@ -58,7 +58,7 @@
 TEST_F(ArrayTest, Is) {
   I32 i32;
 
-  Array arr{&i32, 3};
+  Array arr{&i32, 3, ArrayDecorationList{}};
   Type* ty = &arr;
   EXPECT_FALSE(ty->Is<AccessControl>());
   EXPECT_FALSE(ty->Is<Alias>());
@@ -77,70 +77,55 @@
 
 TEST_F(ArrayTest, TypeName) {
   I32 i32;
-  Array arr{&i32};
+  Array arr{&i32, 0, ArrayDecorationList{}};
   EXPECT_EQ(arr.type_name(), "__array__i32");
 }
 
 TEST_F(ArrayTest, TypeName_RuntimeArray) {
   I32 i32;
-  Array arr{&i32, 3};
+  Array arr{&i32, 3, ArrayDecorationList{}};
   EXPECT_EQ(arr.type_name(), "__array__i32_3");
 }
 
 TEST_F(ArrayTest, TypeName_WithStride) {
   I32 i32;
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(16, Source{}));
-
-  Array arr{&i32, 3};
-  arr.set_decorations(decos);
+  Array arr{&i32, 3,
+            ArrayDecorationList{create<StrideDecoration>(16, Source{})}};
   EXPECT_EQ(arr.type_name(), "__array__i32_3_stride_16");
 }
 
 TEST_F(ArrayTest, MinBufferBindingSizeNoStride) {
   U32 u32;
-  Array arr(&u32, 4);
+  Array arr(&u32, 4, ArrayDecorationList{});
   EXPECT_EQ(0u, arr.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(ArrayTest, MinBufferBindingSizeArray) {
   U32 u32;
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-
-  Array arr(&u32, 4);
-  arr.set_decorations(decos);
+  Array arr(&u32, 4,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   EXPECT_EQ(16u, arr.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(ArrayTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-
-  Array arr(&u32);
-  arr.set_decorations(decos);
+  Array arr(&u32, 0,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   EXPECT_EQ(4u, arr.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(ArrayTest, BaseAlignmentArray) {
   U32 u32;
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-
-  Array arr(&u32, 4);
-  arr.set_decorations(decos);
+  Array arr(&u32, 4,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   EXPECT_EQ(16u, arr.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, arr.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
 
 TEST_F(ArrayTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  ArrayDecorationList decos;
-  decos.push_back(create<StrideDecoration>(4, Source{}));
-
-  Array arr(&u32);
-  arr.set_decorations(decos);
+  Array arr(&u32, 0,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
   EXPECT_EQ(16u, arr.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, arr.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
diff --git a/src/ast/type/matrix_type.cc b/src/ast/type/matrix_type.cc
index ed865a7..12eea45 100644
--- a/src/ast/type/matrix_type.cc
+++ b/src/ast/type/matrix_type.cc
@@ -52,7 +52,7 @@
 
 uint64_t Matrix::BaseAlignment(MemoryLayout mem_layout) const {
   Vector vec(subtype_, rows_);
-  Array arr(&vec, columns_);
+  Array arr(&vec, columns_, ArrayDecorationList{});
   return arr.BaseAlignment(mem_layout);
 }
 
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 3dd11f1..7e28685 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -99,12 +99,8 @@
 
 TEST_F(StructTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array arr(&u32, 4);
-  {
-    ArrayDecorationList decos;
-    decos.push_back(create<StrideDecoration>(4, Source{}));
-    arr.set_decorations(decos);
-  }
+  Array arr(&u32, 4,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
 
   StructMemberList members;
   {
@@ -134,12 +130,8 @@
 
 TEST_F(StructTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array arr(&u32);
-  {
-    ArrayDecorationList decos;
-    decos.push_back(create<StrideDecoration>(4, Source{}));
-    arr.set_decorations(decos);
-  }
+  Array arr(&u32, 0,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
 
   StructMemberList members;
   {
@@ -248,12 +240,8 @@
 
 TEST_F(StructTest, BaseAlignmentArray) {
   U32 u32;
-  Array arr(&u32, 4);
-  {
-    ArrayDecorationList decos;
-    decos.push_back(create<StrideDecoration>(4, Source{}));
-    arr.set_decorations(decos);
-  }
+  Array arr(&u32, 4,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
 
   StructMemberList members;
   {
@@ -281,12 +269,8 @@
 
 TEST_F(StructTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array arr(&u32);
-  {
-    ArrayDecorationList decos;
-    decos.push_back(create<StrideDecoration>(4, Source{}));
-    arr.set_decorations(decos);
-  }
+  Array arr(&u32, 0,
+            ArrayDecorationList{create<StrideDecoration>(4, Source{})});
 
   StructMemberList members;
   {
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 9439593..9014d26 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -675,13 +675,13 @@
   ast::type::U32* u32_type() { return &u32_type_; }
   ast::type::Array* u32_array_type(uint32_t count) {
     if (array_type_memo_.find(count) == array_type_memo_.end()) {
-      array_type_memo_[count] =
-          std::make_unique<ast::type::Array>(u32_type(), count);
-      ast::ArrayDecorationList decos;
-      decos.push_back(create<ast::StrideDecoration>(4, Source{}));
-      array_type_memo_[count]->set_decorations(decos);
+      array_type_memo_[count] = create<ast::type::Array>(
+          u32_type(), count,
+          ast::ArrayDecorationList{
+              create<ast::StrideDecoration>(4, Source{}),
+          });
     }
-    return array_type_memo_[count].get();
+    return array_type_memo_[count];
   }
   ast::type::Vector* vec_type(ast::type::Type* type, uint32_t count) {
     if (vector_type_memo_.find(std::tie(type, count)) ==
@@ -718,7 +718,7 @@
   ast::type::Void void_type_;
   ast::type::Sampler sampler_type_;
   ast::type::Sampler comparison_sampler_type_;
-  std::map<uint32_t, std::unique_ptr<ast::type::Array>> array_type_memo_;
+  std::map<uint32_t, ast::type::Array*> array_type_memo_;
   std::map<std::tuple<ast::type::Type*, uint32_t>,
            std::unique_ptr<ast::type::Vector>>
       vector_type_memo_;
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 202293d..12908b4 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -710,11 +710,11 @@
   if (ast_elem_ty == nullptr) {
     return nullptr;
   }
-  auto ast_type = std::make_unique<ast::type::Array>(ast_elem_ty);
-  if (!ApplyArrayDecorations(rtarr_ty, ast_type.get())) {
+  ast::ArrayDecorationList decorations;
+  if (!ParseArrayDecorations(rtarr_ty, &decorations)) {
     return nullptr;
   }
-  return ast_module_.unique_type(std::move(ast_type));
+  return create<ast::type::Array>(ast_elem_ty, 0, std::move(decorations));
 }
 
 ast::type::Type* ParserImpl::ConvertType(
@@ -751,20 +751,22 @@
            << num_elem;
     return nullptr;
   }
-  auto ast_type = std::make_unique<ast::type::Array>(
-      ast_elem_ty, static_cast<uint32_t>(num_elem));
-  if (!ApplyArrayDecorations(arr_ty, ast_type.get())) {
+  ast::ArrayDecorationList decorations;
+  if (!ParseArrayDecorations(arr_ty, &decorations)) {
     return nullptr;
   }
+
   if (remap_buffer_block_type_.count(elem_type_id)) {
     remap_buffer_block_type_.insert(type_mgr_->GetId(arr_ty));
   }
-  return ast_module_.unique_type(std::move(ast_type));
+  return create<ast::type::Array>(ast_elem_ty, static_cast<uint32_t>(num_elem),
+                                  std::move(decorations));
 }
 
-bool ParserImpl::ApplyArrayDecorations(
+bool ParserImpl::ParseArrayDecorations(
     const spvtools::opt::analysis::Type* spv_type,
-    ast::type::Array* ast_type) {
+    ast::ArrayDecorationList* decorations) {
+  bool has_array_stride = false;
   const auto type_id = type_mgr_->GetId(spv_type);
   for (auto& decoration : this->GetDecorationsFor(type_id)) {
     if (decoration.size() == 2 && decoration[0] == SpvDecorationArrayStride) {
@@ -773,13 +775,12 @@
         return Fail() << "invalid array type ID " << type_id
                       << ": ArrayStride can't be 0";
       }
-      if (ast_type->has_array_stride()) {
+      if (has_array_stride) {
         return Fail() << "invalid array type ID " << type_id
                       << ": multiple ArrayStride decorations";
       }
-      ast::ArrayDecorationList decos;
-      decos.push_back(create<ast::StrideDecoration>(stride, Source{}));
-      ast_type->set_decorations(std::move(decos));
+      has_array_stride = true;
+      decorations->push_back(create<ast::StrideDecoration>(stride, Source{}));
     } else {
       return Fail() << "invalid array type ID " << type_id
                     << ": unknown decoration "
diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h
index 6530d9e..346fecb 100644
--- a/src/reader/spirv/parser_impl.h
+++ b/src/reader/spirv/parser_impl.h
@@ -492,12 +492,12 @@
   ast::type::Type* ConvertType(uint32_t type_id,
                                const spvtools::opt::analysis::Pointer* ptr_ty);
 
-  /// Applies SPIR-V decorations to the given array or runtime-array type.
-  /// @param spv_type the SPIR-V aray or runtime-array type.
-  /// @param ast_type non-null; the AST type to apply decorations to
+  /// Parses the array or runtime-array decorations.
+  /// @param spv_type the SPIR-V array or runtime-array type.
+  /// @param decorations the populated decoration list
   /// @returns true on success.
-  bool ApplyArrayDecorations(const spvtools::opt::analysis::Type* spv_type,
-                             ast::type::Array* ast_type);
+  bool ParseArrayDecorations(const spvtools::opt::analysis::Type* spv_type,
+                             ast::ArrayDecorationList* decorations);
 
   /// Creates a new `ast::Node` owned by the Module. When the Module is
   /// destructed, the `ast::Node` will also be destructed.
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index ad88c80..8a3b076 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -1099,9 +1099,7 @@
       size = val.value;
     }
 
-    auto ty = std::make_unique<ast::type::Array>(subtype.value, size);
-    ty->set_decorations(std::move(decos));
-    return module_.unique_type(std::move(ty));
+    return create<ast::type::Array>(subtype.value, size, std::move(decos));
   });
 }
 
diff --git a/src/transform/vertex_pulling.cc b/src/transform/vertex_pulling.cc
index 5614ba4..8be6582 100644
--- a/src/transform/vertex_pulling.cc
+++ b/src/transform/vertex_pulling.cc
@@ -239,12 +239,11 @@
 void VertexPulling::State::AddVertexStorageBuffers() {
   // TODO(idanr): Make this readonly https://github.com/gpuweb/gpuweb/issues/935
   // The array inside the struct definition
-  auto internal_array = std::make_unique<ast::type::Array>(GetU32Type());
-  ast::ArrayDecorationList ary_decos;
-  ary_decos.push_back(mod->create<ast::StrideDecoration>(4u, Source{}));
-  internal_array->set_decorations(std::move(ary_decos));
-
-  auto* internal_array_type = mod->unique_type(std::move(internal_array));
+  auto* internal_array_type = mod->create<ast::type::Array>(
+      GetU32Type(), 0,
+      ast::ArrayDecorationList{
+          mod->create<ast::StrideDecoration>(4u, Source{}),
+      });
 
   // Creating the struct type
   ast::StructMemberList members;
diff --git a/src/transform/vertex_pulling_test.cc b/src/transform/vertex_pulling_test.cc
index 820d1e0..ab16882 100644
--- a/src/transform/vertex_pulling_test.cc
+++ b/src/transform/vertex_pulling_test.cc
@@ -579,7 +579,7 @@
   ast::type::F32 f32;
   AddVertexInputVariable(0, "var_a", &f32);
 
-  ast::type::Array vec4_f32{&f32, 4u};
+  ast::type::Array vec4_f32{&f32, 4u, ast::ArrayDecorationList{}};
   AddVertexInputVariable(1, "var_b", &vec4_f32);
 
   InitTransform(
@@ -759,13 +759,13 @@
   InitBasicModule();
 
   ast::type::F32 f32;
-  ast::type::Array vec2_f32{&f32, 2u};
+  ast::type::Array vec2_f32{&f32, 2u, ast::ArrayDecorationList{}};
   AddVertexInputVariable(0, "var_a", &vec2_f32);
 
-  ast::type::Array vec3_f32{&f32, 3u};
+  ast::type::Array vec3_f32{&f32, 3u, ast::ArrayDecorationList{}};
   AddVertexInputVariable(1, "var_b", &vec3_f32);
 
-  ast::type::Array vec4_f32{&f32, 4u};
+  ast::type::Array vec4_f32{&f32, 4u, ast::ArrayDecorationList{}};
   AddVertexInputVariable(2, "var_c", &vec4_f32);
 
   InitTransform(
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index a761335..0b217a4 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -428,7 +428,7 @@
 TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array) {
   ast::type::I32 i32;
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 3);
+  ast::type::Array ary(&f32, 3, ast::ArrayDecorationList{});
 
   auto* idx = create<ast::ScalarConstructorExpression>(
       create<ast::SintLiteral>(&i32, 2));
@@ -452,7 +452,7 @@
 TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Alias_Array) {
   ast::type::I32 i32;
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 3);
+  ast::type::Array ary(&f32, 3, ast::ArrayDecorationList{});
   ast::type::Alias aary("myarrty", &ary);
 
   auto* idx = create<ast::ScalarConstructorExpression>(
@@ -477,7 +477,7 @@
 TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array_Constant) {
   ast::type::I32 i32;
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 3);
+  ast::type::Array ary(&f32, 3, ast::ArrayDecorationList{});
 
   auto* idx = create<ast::ScalarConstructorExpression>(
       create<ast::SintLiteral>(&i32, 2));
diff --git a/src/validator/validator_type_test.cc b/src/validator/validator_type_test.cc
index fbec490..2195c92 100644
--- a/src/validator/validator_type_test.cc
+++ b/src/validator/validator_type_test.cc
@@ -43,7 +43,7 @@
   // };
 
   ast::type::F32 f32;
-  ast::type::Array arr(&f32);
+  ast::type::Array arr(&f32, 0, ast::ArrayDecorationList{});
   ast::StructMemberList members;
   {
     ast::StructMemberDecorationList deco;
@@ -70,7 +70,7 @@
   // };
 
   ast::type::F32 f32;
-  ast::type::Array arr(&f32);
+  ast::type::Array arr(&f32, 0, ast::ArrayDecorationList{});
   ast::StructMemberList members;
   {
     ast::StructMemberDecorationList deco;
@@ -100,7 +100,7 @@
   // };
 
   ast::type::F32 f32;
-  ast::type::Array arr(&f32);
+  ast::type::Array arr(&f32, 0, ast::ArrayDecorationList{});
   ast::StructMemberList members;
   {
     ast::StructMemberDecorationList deco;
@@ -132,7 +132,7 @@
   //}
 
   ast::type::F32 u32;
-  ast::type::Array array(&u32);
+  ast::type::Array array(&u32, 0, ast::ArrayDecorationList{});
   ast::type::Alias alias{"RTArr", &array};
 
   ast::StructMemberList members;
@@ -166,7 +166,7 @@
   //}
 
   ast::type::F32 u32;
-  ast::type::Array array(&u32);
+  ast::type::Array array(&u32, 0, ast::ArrayDecorationList{});
   ast::type::Alias alias{"RTArr", &array};
 
   ast::StructMemberList members;
@@ -191,7 +191,7 @@
   /// [[stage(vertex)]]
   // fn func -> void { var a : array<i32>; }
   ast::type::I32 i32;
-  ast::type::Array array(&i32);
+  ast::type::Array array(&i32, 0, ast::ArrayDecorationList{});
 
   auto* var =
       create<ast::Variable>(Source{}, "a", ast::StorageClass::kNone, &array);
diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc
index 12033c1..3bbdbc7 100644
--- a/src/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/writer/hlsl/generator_impl_constructor_test.cc
@@ -193,7 +193,7 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Array) {
   ast::type::F32 f32;
   ast::type::Vector vec(&f32, 3);
-  ast::type::Array ary(&vec, 3);
+  ast::type::Array ary(&vec, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList ary_values;
 
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index 315394c..cc35e8a 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -1037,7 +1037,7 @@
 
 TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayParams) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 5);
+  ast::type::Array ary(&f32, 5, ast::ArrayDecorationList{});
 
   ast::VariableList params;
   params.push_back(
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index 648d38c..5e1cc955 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -477,8 +477,10 @@
   // -> asint(data.Load((2 * 4));
   ast::type::F32 f32;
   ast::type::I32 i32;
-  ast::type::Array ary(&i32, 5);
-  ary.set_decorations({create<ast::StrideDecoration>(4, Source{})});
+  ast::type::Array ary(&i32, 5,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(4, Source{}),
+                       });
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
@@ -521,8 +523,10 @@
   // -> asint(data.Load((4 * ((2 + 4) - 3)));
   ast::type::F32 f32;
   ast::type::I32 i32;
-  ast::type::Array ary(&i32, 5);
-  ary.set_decorations({create<ast::StrideDecoration>(4, Source{})});
+  ast::type::Array ary(&i32, 5,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(4, Source{}),
+                       });
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
@@ -623,8 +627,10 @@
 
   ast::type::F32 f32;
   ast::type::I32 i32;
-  ast::type::Array ary(&i32, 5);
-  ary.set_decorations({create<ast::StrideDecoration>(4, Source{})});
+  ast::type::Array ary(&i32, 5,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(4, Source{}),
+                       });
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
@@ -848,8 +854,10 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(&data, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(32, Source{}),
+                       });
 
   auto* pre_str = create<ast::Struct>(ast::StructMemberList{
       create<ast::StructMember>(
@@ -919,8 +927,9 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(
+      &data, 4,
+      ast::ArrayDecorationList{create<ast::StrideDecoration>(32, Source{})});
 
   auto* pre_str =
       create<ast::Struct>(ast::StructMemberList{create<ast::StructMember>(
@@ -989,8 +998,10 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(&data, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(32, Source{}),
+                       });
 
   auto* pre_str =
       create<ast::Struct>(ast::StructMemberList{create<ast::StructMember>(
@@ -1058,8 +1069,10 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(&data, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(32, Source{}),
+                       });
 
   auto* pre_str =
       create<ast::Struct>(ast::StructMemberList{create<ast::StructMember>(
@@ -1128,8 +1141,10 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(&data, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(32, Source{}),
+                       });
 
   auto* pre_str =
       create<ast::Struct>(ast::StructMemberList{create<ast::StructMember>(
@@ -1209,8 +1224,10 @@
 
   ast::type::Struct data("Data", data_str);
 
-  ast::type::Array ary(&data, 4);
-  ary.set_decorations({create<ast::StrideDecoration>(32, Source{})});
+  ast::type::Array ary(&data, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(32, Source{}),
+                       });
 
   auto* pre_str =
       create<ast::Struct>(ast::StructMemberList{create<ast::StructMember>(
diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc
index 884b754..4786c4d 100644
--- a/src/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/writer/hlsl/generator_impl_module_constant_test.cc
@@ -35,7 +35,7 @@
 
 TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 3);
+  ast::type::Array ary(&f32, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList exprs;
   exprs.push_back(create<ast::ScalarConstructorExpression>(
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index b2156f7..0f8f36d 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -61,7 +61,7 @@
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_Array) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &a, "ary")) << gen.error();
   EXPECT_EQ(result(), "bool ary[4]");
@@ -69,8 +69,8 @@
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &c, "ary")) << gen.error();
   EXPECT_EQ(result(), "bool ary[5][4]");
@@ -80,9 +80,9 @@
 TEST_F(HlslGeneratorImplTest_Type,
        DISABLED_EmitType_ArrayOfArrayOfRuntimeArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
-  ast::type::Array d(&c);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
+  ast::type::Array d(&c, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &c, "ary")) << gen.error();
   EXPECT_EQ(result(), "bool ary[5][4][1]");
@@ -90,9 +90,9 @@
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArrayOfArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
-  ast::type::Array d(&c, 6);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
+  ast::type::Array d(&c, 6, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &d, "ary")) << gen.error();
   EXPECT_EQ(result(), "bool ary[6][5][4]");
@@ -100,7 +100,7 @@
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_NameCollision) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &a, "bool")) << gen.error();
   EXPECT_EQ(result(), "bool bool_tint_0[4]");
@@ -108,7 +108,7 @@
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &a, "")) << gen.error();
   EXPECT_EQ(result(), "bool[4]");
@@ -116,7 +116,7 @@
 
 TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_RuntimeArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b);
+  ast::type::Array a(&b, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &a, "ary")) << gen.error();
   EXPECT_EQ(result(), "bool ary[]");
@@ -125,7 +125,7 @@
 TEST_F(HlslGeneratorImplTest_Type,
        DISABLED_EmitType_RuntimeArray_NameCollision) {
   ast::type::Bool b;
-  ast::type::Array a(&b);
+  ast::type::Array a(&b, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(out, &a, "double")) << gen.error();
   EXPECT_EQ(result(), "bool double_tint_0[]");
diff --git a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index b4e389f..e006551 100644
--- a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -59,7 +59,7 @@
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 5);
+  ast::type::Array ary(&f32, 5, ast::ArrayDecorationList{});
 
   auto* var =
       create<ast::Variable>(Source{}, "a", ast::StorageClass::kNone, &ary);
diff --git a/src/writer/msl/generator_impl_constructor_test.cc b/src/writer/msl/generator_impl_constructor_test.cc
index 223257a..cd83117 100644
--- a/src/writer/msl/generator_impl_constructor_test.cc
+++ b/src/writer/msl/generator_impl_constructor_test.cc
@@ -194,7 +194,7 @@
 TEST_F(MslGeneratorImplTest, EmitConstructor_Type_Array) {
   ast::type::F32 f32;
   ast::type::Vector vec(&f32, 3);
-  ast::type::Array ary(&vec, 3);
+  ast::type::Array ary(&vec, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList ary_values;
 
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 5290a23..5e14775 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -1011,7 +1011,7 @@
 
 TEST_F(MslGeneratorImplTest, Emit_Function_WithArrayParams) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 5);
+  ast::type::Array ary(&f32, 5, ast::ArrayDecorationList{});
 
   ast::VariableList params;
   params.push_back(
diff --git a/src/writer/msl/generator_impl_module_constant_test.cc b/src/writer/msl/generator_impl_module_constant_test.cc
index 97007b7..fc5739a 100644
--- a/src/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/writer/msl/generator_impl_module_constant_test.cc
@@ -37,7 +37,7 @@
 
 TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 3);
+  ast::type::Array ary(&f32, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList exprs;
   exprs.push_back(create<ast::ScalarConstructorExpression>(
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index c32e429..06fdbc7 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -123,7 +123,7 @@
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_array) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 4);
+  ast::type::Array ary(&f32, 4, ast::ArrayDecorationList{});
   EXPECT_EQ(4u * 4u, gen.calculate_alignment_size(&ary));
 }
 
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index 9854cf1..54fd68b 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -64,7 +64,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_Array) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a, "ary")) << gen.error();
   EXPECT_EQ(gen.result(), "bool ary[4]");
@@ -72,8 +72,8 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&c, "ary")) << gen.error();
   EXPECT_EQ(gen.result(), "bool ary[5][4]");
@@ -82,9 +82,9 @@
 // TODO(dsinclair): Is this possible? What order should it output in?
 TEST_F(MslGeneratorImplTest, DISABLED_EmitType_ArrayOfArrayOfRuntimeArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
-  ast::type::Array d(&c);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
+  ast::type::Array d(&c, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&c, "ary")) << gen.error();
   EXPECT_EQ(gen.result(), "bool ary[5][4][1]");
@@ -92,9 +92,9 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
-  ast::type::Array c(&a, 5);
-  ast::type::Array d(&c, 6);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
+  ast::type::Array c(&a, 5, ast::ArrayDecorationList{});
+  ast::type::Array d(&c, 6, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&d, "ary")) << gen.error();
   EXPECT_EQ(gen.result(), "bool ary[6][5][4]");
@@ -102,7 +102,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_Array_NameCollision) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a, "bool")) << gen.error();
   EXPECT_EQ(gen.result(), "bool bool_tint_0[4]");
@@ -110,7 +110,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_Array_WithoutName) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a, "")) << gen.error();
   EXPECT_EQ(gen.result(), "bool[4]");
@@ -118,7 +118,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b);
+  ast::type::Array a(&b, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a, "ary")) << gen.error();
   EXPECT_EQ(gen.result(), "bool ary[1]");
@@ -126,7 +126,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray_NameCollision) {
   ast::type::Bool b;
-  ast::type::Array a(&b);
+  ast::type::Array a(&b, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a, "discard_fragment")) << gen.error();
   EXPECT_EQ(gen.result(), "bool discard_fragment_tint_0[1]");
diff --git a/src/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
index dcaf542..f8eac4a 100644
--- a/src/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -69,7 +69,7 @@
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Array) {
   ast::type::F32 f32;
-  ast::type::Array ary(&f32, 5);
+  ast::type::Array ary(&f32, 5, ast::ArrayDecorationList{});
 
   auto* var =
       create<ast::Variable>(Source{}, "a", ast::StorageClass::kNone, &ary);
diff --git a/src/writer/spirv/builder_accessor_expression_test.cc b/src/writer/spirv/builder_accessor_expression_test.cc
index 65b66c4..604ffa5 100644
--- a/src/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/writer/spirv/builder_accessor_expression_test.cc
@@ -181,7 +181,7 @@
   ast::type::I32 i32;
   ast::type::F32 f32;
   ast::type::Vector vec3(&f32, 3);
-  ast::type::Array ary4(&vec3, 4);
+  ast::type::Array ary4(&vec3, 4, ast::ArrayDecorationList{});
 
   // ary = array<vec3<f32>, 4>
   // ary[3][2];
@@ -228,7 +228,7 @@
   ast::type::I32 i32;
   ast::type::F32 f32;
   ast::type::Vector vec3(&f32, 3);
-  ast::type::Array ary4(&vec3, 4);
+  ast::type::Array ary4(&vec3, 4, ast::ArrayDecorationList{});
 
   // var a : array<vec3<f32>, 4>;
   // a[2].xy;
@@ -784,13 +784,13 @@
       ast::StructMemberList{create<ast::StructMember>("bar", &c_type, decos)});
   ast::type::Struct b_type("B", s);
 
-  ast::type::Array b_ary_type(&b_type, 3);
+  ast::type::Array b_ary_type(&b_type, 3, ast::ArrayDecorationList{});
 
   s = create<ast::Struct>(ast::StructMemberList{
       create<ast::StructMember>("foo", &b_ary_type, decos)});
   ast::type::Struct a_type("A", s);
 
-  ast::type::Array a_ary_type(&a_type, 2);
+  ast::type::Array a_ary_type(&a_type, 2, ast::ArrayDecorationList{});
 
   ast::Variable var(Source{}, "index", ast::StorageClass::kFunction,
                     &a_ary_type);
@@ -858,7 +858,7 @@
   ast::type::F32 f32;
   ast::type::U32 u32;
   ast::type::Vector vec(&f32, 2);
-  ast::type::Array arr(&vec, 3);
+  ast::type::Array arr(&vec, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList ary_params;
   ary_params.push_back(create<ast::TypeConstructorExpression>(
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc
index 0a1c200..0dbad7d 100644
--- a/src/writer/spirv/builder_type_test.cc
+++ b/src/writer/spirv/builder_type_test.cc
@@ -81,7 +81,7 @@
 
 TEST_F(BuilderTest_Type, GenerateRuntimeArray) {
   ast::type::I32 i32;
-  ast::type::Array ary(&i32);
+  ast::type::Array ary(&i32, 0, ast::ArrayDecorationList{});
 
   auto id = b.GenerateTypeIfNeeded(&ary);
   ASSERT_FALSE(b.has_error()) << b.error();
@@ -94,7 +94,7 @@
 
 TEST_F(BuilderTest_Type, ReturnsGeneratedRuntimeArray) {
   ast::type::I32 i32;
-  ast::type::Array ary(&i32);
+  ast::type::Array ary(&i32, 0, ast::ArrayDecorationList{});
 
   EXPECT_EQ(b.GenerateTypeIfNeeded(&ary), 1u);
   EXPECT_EQ(b.GenerateTypeIfNeeded(&ary), 1u);
@@ -107,7 +107,7 @@
 
 TEST_F(BuilderTest_Type, GenerateArray) {
   ast::type::I32 i32;
-  ast::type::Array ary(&i32, 4);
+  ast::type::Array ary(&i32, 4, ast::ArrayDecorationList{});
 
   auto id = b.GenerateTypeIfNeeded(&ary);
   ASSERT_FALSE(b.has_error()) << b.error();
@@ -123,11 +123,10 @@
 TEST_F(BuilderTest_Type, GenerateArray_WithStride) {
   ast::type::I32 i32;
 
-  ast::ArrayDecorationList decos;
-  decos.push_back(create<ast::StrideDecoration>(16u, Source{}));
-
-  ast::type::Array ary(&i32, 4);
-  ary.set_decorations(decos);
+  ast::type::Array ary(&i32, 4,
+                       ast::ArrayDecorationList{
+                           create<ast::StrideDecoration>(16u, Source{}),
+                       });
 
   auto id = b.GenerateTypeIfNeeded(&ary);
   ASSERT_FALSE(b.has_error()) << b.error();
@@ -145,7 +144,7 @@
 
 TEST_F(BuilderTest_Type, ReturnsGeneratedArray) {
   ast::type::I32 i32;
-  ast::type::Array ary(&i32, 4);
+  ast::type::Array ary(&i32, 4, ast::ArrayDecorationList{});
 
   EXPECT_EQ(b.GenerateTypeIfNeeded(&ary), 1u);
   EXPECT_EQ(b.GenerateTypeIfNeeded(&ary), 1u);
@@ -471,14 +470,17 @@
   ast::type::F32 f32;
 
   ast::type::Matrix glsl_mat2x2(&f32, 2, 2);
-  ast::type::Array arr_mat2x2(&glsl_mat2x2, 1);  // Singly nested array
+  ast::type::Array arr_mat2x2(
+      &glsl_mat2x2, 1, ast::ArrayDecorationList{});  // Singly nested array
 
   ast::type::Matrix glsl_mat2x3(&f32, 3, 2);  // 2 columns, 3 rows
-  ast::type::Array arr_mat2x3(&glsl_mat2x3, 1);
-  ast::type::Array arr_arr_mat2x2(&arr_mat2x3, 1);  // Doubly nested array
+  ast::type::Array arr_mat2x3(&glsl_mat2x3, 1, ast::ArrayDecorationList{});
+  ast::type::Array arr_arr_mat2x2(
+      &arr_mat2x3, 1, ast::ArrayDecorationList{});  // Doubly nested array
 
   ast::type::Matrix glsl_mat4x4(&f32, 4, 4);
-  ast::type::Array rtarr_mat4x4(&glsl_mat4x4);  // Runtime array
+  ast::type::Array rtarr_mat4x4(&glsl_mat4x4, 0,
+                                ast::ArrayDecorationList{});  // Runtime array
 
   ast::StructMemberDecorationList a_decos;
   a_decos.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
diff --git a/src/writer/wgsl/generator_impl_constructor_test.cc b/src/writer/wgsl/generator_impl_constructor_test.cc
index 0993355..14da9a1 100644
--- a/src/writer/wgsl/generator_impl_constructor_test.cc
+++ b/src/writer/wgsl/generator_impl_constructor_test.cc
@@ -174,7 +174,7 @@
 TEST_F(WgslGeneratorImplTest, EmitConstructor_Type_Array) {
   ast::type::F32 f32;
   ast::type::Vector vec(&f32, 3);
-  ast::type::Array ary(&vec, 3);
+  ast::type::Array ary(&vec, 3, ast::ArrayDecorationList{});
 
   ast::ExpressionList ary_values;
 
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc
index 7693db2..048e72b 100644
--- a/src/writer/wgsl/generator_impl_type_test.cc
+++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -57,7 +57,7 @@
 
 TEST_F(WgslGeneratorImplTest, EmitType_Array) {
   ast::type::Bool b;
-  ast::type::Array a(&b, 4);
+  ast::type::Array a(&b, 4, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a)) << gen.error();
   EXPECT_EQ(gen.result(), "array<bool, 4>");
@@ -105,11 +105,10 @@
 
 TEST_F(WgslGeneratorImplTest, EmitType_Array_Decoration) {
   ast::type::Bool b;
-  ast::ArrayDecorationList decos;
-  decos.push_back(create<ast::StrideDecoration>(16u, Source{}));
-
-  ast::type::Array a(&b, 4);
-  a.set_decorations(decos);
+  ast::type::Array a(&b, 4,
+                     ast::ArrayDecorationList{
+                         create<ast::StrideDecoration>(16u, Source{}),
+                     });
 
   ASSERT_TRUE(gen.EmitType(&a)) << gen.error();
   EXPECT_EQ(gen.result(), "[[stride(16)]] array<bool, 4>");
@@ -117,12 +116,11 @@
 
 TEST_F(WgslGeneratorImplTest, EmitType_Array_MultipleDecorations) {
   ast::type::Bool b;
-  ast::ArrayDecorationList decos;
-  decos.push_back(create<ast::StrideDecoration>(16u, Source{}));
-  decos.push_back(create<ast::StrideDecoration>(32u, Source{}));
-
-  ast::type::Array a(&b, 4);
-  a.set_decorations(decos);
+  ast::type::Array a(&b, 4,
+                     ast::ArrayDecorationList{
+                         create<ast::StrideDecoration>(16u, Source{}),
+                         create<ast::StrideDecoration>(32u, Source{}),
+                     });
 
   ASSERT_TRUE(gen.EmitType(&a)) << gen.error();
   EXPECT_EQ(gen.result(), "[[stride(16)]] [[stride(32)]] array<bool, 4>");
@@ -130,7 +128,7 @@
 
 TEST_F(WgslGeneratorImplTest, EmitType_RuntimeArray) {
   ast::type::Bool b;
-  ast::type::Array a(&b);
+  ast::type::Array a(&b, 0, ast::ArrayDecorationList{});
 
   ASSERT_TRUE(gen.EmitType(&a)) << gen.error();
   EXPECT_EQ(gen.result(), "array<bool>");