tint/utils: Remove non-const accessors on VectorRef

Nothing uses these, and the mutability of these breaks
const-correctness.

Switch functions that used to return `const utils::Vector<T, N>&`
to returning `utils::VectorRef<T>`. Removes the templated size from the
public interface.

Replace all `const utils::VectorRef<T>&` with `utils::Vector<T>`,
there's no point in using yet another level of pointer indirection.

Change-Id: Ib96e3171500606d9afffbb13f40023552a74fffc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113021
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index 25cde92..ea5b3ed 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -532,7 +532,7 @@
                                       ResourceBinding::ResourceType::kExternalTexture);
 }
 
-utils::Vector<sem::SamplerTexturePair, 4> Inspector::GetSamplerTextureUses(
+utils::VectorRef<sem::SamplerTexturePair> Inspector::GetSamplerTextureUses(
     const std::string& entry_point) {
     auto* func = FindEntryPointByName(entry_point);
     if (!func) {
diff --git a/src/tint/inspector/inspector.h b/src/tint/inspector/inspector.h
index 49e4bdf..62a1c73 100644
--- a/src/tint/inspector/inspector.h
+++ b/src/tint/inspector/inspector.h
@@ -126,7 +126,7 @@
     /// @param entry_point name of the entry point to get information about.
     /// @returns vector of all of the sampler/texture sampling pairs that are used
     /// by that entry point.
-    utils::Vector<sem::SamplerTexturePair, 4> GetSamplerTextureUses(const std::string& entry_point);
+    utils::VectorRef<sem::SamplerTexturePair> GetSamplerTextureUses(const std::string& entry_point);
 
     /// @param entry_point name of the entry point to get information about.
     /// @param placeholder the sampler binding point to use for texture-only
diff --git a/src/tint/inspector/inspector_test.cc b/src/tint/inspector/inspector_test.cc
index 05f3c19..83302e2 100644
--- a/src/tint/inspector/inspector_test.cc
+++ b/src/tint/inspector/inspector_test.cc
@@ -12,7 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
 #include "src/tint/ast/call_statement.h"
 #include "src/tint/ast/disable_validation_attribute.h"
 #include "src/tint/ast/id_attribute.h"
@@ -33,16 +34,13 @@
 namespace tint::inspector {
 namespace {
 
-// All the tests that descend from InspectorBuilder are expected to define their
-// test state via building up the AST through InspectorBuilder and then generate
-// the program with ::Build.
-// The returned Inspector from ::Build can then be used to test expecations.
+// All the tests that descend from InspectorBuilder are expected to define their test state via
+// building up the AST through InspectorBuilder and then generate the program with ::Build. The
+// returned Inspector from ::Build can then be used to test expectations.
 //
-// All the tests that descend from InspectorRunner are expected to define their
-// test state via a WGSL shader, which will be parsed to generate a Program and
-// Inspector in ::Initialize.
-// The returned Inspector from ::Initialize can then be used to test
-// expecations.
+// All the tests that descend from InspectorRunner are expected to define their test state via a
+// WGSL shader, which will be parsed to generate a Program and Inspector in ::Initialize. The
+// returned Inspector from ::Initialize can then be used to test expectations.
 
 class InspectorGetEntryPointTest : public InspectorBuilder, public testing::Test {};
 
@@ -3202,7 +3200,7 @@
 })";
 
     Inspector& inspector = Initialize(shader);
-    auto result = inspector.GetSamplerTextureUses("foo");
+    inspector.GetSamplerTextureUses("foo");
     ASSERT_TRUE(inspector.has_error()) << inspector.error();
 }
 
@@ -3224,7 +3222,8 @@
     auto result_1 = inspector.GetSamplerTextureUses("main");
     ASSERT_FALSE(inspector.has_error()) << inspector.error();
 
-    EXPECT_EQ(result_0, result_1);
+    EXPECT_EQ((utils::Vector<tint::sem::SamplerTexturePair, 4>(result_0)),
+              (utils::Vector<tint::sem::SamplerTexturePair, 4>(result_1)));
 }
 
 TEST_F(InspectorGetSamplerTextureUsesTest, BothIndirect) {
@@ -3641,7 +3640,7 @@
 })";
 
     Inspector& inspector = Initialize(shader);
-    auto result = inspector.GetSamplerTextureUses("main");
+    inspector.GetSamplerTextureUses("main");
 }
 
 }  // namespace
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index 0f0200d..35e4f70 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -77,7 +77,7 @@
     return ir_switch;
 }
 
-Block* Builder::CreateCase(Switch* s, const utils::VectorRef<const ast::CaseSelector*> selectors) {
+Block* Builder::CreateCase(Switch* s, utils::VectorRef<const ast::CaseSelector*> selectors) {
     s->cases.Push(Switch::Case{selectors, CreateBlock()});
 
     Block* b = s->cases.Back().start_target;
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 3f2e011..ceabfa6 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -78,7 +78,7 @@
     /// @param s the switch to create the case into
     /// @param selectors the case selectors for the case statement
     /// @returns the start block for the case flow node
-    Block* CreateCase(Switch* s, const utils::VectorRef<const ast::CaseSelector*> selectors);
+    Block* CreateCase(Switch* s, utils::VectorRef<const ast::CaseSelector*> selectors);
 
     /// Branches the given block to the given flow node.
     /// @param from the block to branch from
diff --git a/src/tint/ir/switch.h b/src/tint/ir/switch.h
index 3ea9c3f..7fff0a0 100644
--- a/src/tint/ir/switch.h
+++ b/src/tint/ir/switch.h
@@ -33,7 +33,7 @@
     /// A case label in the struct
     struct Case {
         /// The case selector for this node
-        const utils::VectorRef<const ast::CaseSelector*> selectors;
+        utils::Vector<const ast::CaseSelector*, 4> selectors;
         /// The start block for the case block.
         Block* start_target;
     };
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index ca66ac2..628bf45 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1745,7 +1745,7 @@
             return nullptr;
         },
         [&](const sem::Struct* s) -> const sem::Type* {
-            if (auto& tys = s->ConcreteTypes(); !tys.IsEmpty()) {
+            if (auto tys = s->ConcreteTypes(); !tys.IsEmpty()) {
                 return target_ty ? target_ty : tys[0];
             }
             return nullptr;
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index e5c7c1a..dcb9b4c 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -1811,7 +1811,7 @@
     return true;
 }
 
-bool Validator::PipelineStages(const utils::VectorRef<sem::Function*> entry_points) const {
+bool Validator::PipelineStages(utils::VectorRef<sem::Function*> entry_points) const {
     auto backtrace = [&](const sem::Function* func, const sem::Function* entry_point) {
         if (func != entry_point) {
             TraverseCallChain(diagnostics_, entry_point, func, [&](const sem::Function* f) {
@@ -1906,7 +1906,7 @@
     return true;
 }
 
-bool Validator::PushConstants(const utils::VectorRef<sem::Function*> entry_points) const {
+bool Validator::PushConstants(utils::VectorRef<sem::Function*> entry_points) const {
     for (auto* entry_point : entry_points) {
         // State checked and modified by check_push_constant so that it remembers previously seen
         // push_constant variables for an entry-point.
@@ -2422,7 +2422,7 @@
     const sem::Type* store_ty,
     ast::Access access,
     ast::AddressSpace address_space,
-    const utils::VectorRef<const tint::ast::Attribute*> attributes,
+    utils::VectorRef<const tint::ast::Attribute*> attributes,
     const Source& source) const {
     if (!AddressSpaceLayout(store_ty, address_space, source)) {
         return false;
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index 0f183bb..9f0664c 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -135,12 +135,12 @@
     /// Validates pipeline stages
     /// @param entry_points the entry points to the module
     /// @returns true on success, false otherwise.
-    bool PipelineStages(const utils::VectorRef<sem::Function*> entry_points) const;
+    bool PipelineStages(utils::VectorRef<sem::Function*> entry_points) const;
 
     /// Validates push_constant variables
     /// @param entry_points the entry points to the module
     /// @returns true on success, false otherwise.
-    bool PushConstants(const utils::VectorRef<sem::Function*> entry_points) const;
+    bool PushConstants(utils::VectorRef<sem::Function*> entry_points) const;
 
     /// Validates aliases
     /// @param alias the alias to validate
@@ -508,7 +508,7 @@
     bool CheckTypeAccessAddressSpace(const sem::Type* store_ty,
                                      ast::Access access,
                                      ast::AddressSpace address_space,
-                                     const utils::VectorRef<const tint::ast::Attribute*> attributes,
+                                     utils::VectorRef<const tint::ast::Attribute*> attributes,
                                      const Source& source) const;
     SymbolTable& symbols_;
     diag::List& diagnostics_;
diff --git a/src/tint/sem/function.h b/src/tint/sem/function.h
index 8f21f74..7b5eaff 100644
--- a/src/tint/sem/function.h
+++ b/src/tint/sem/function.h
@@ -135,9 +135,7 @@
 
     /// @returns the list of texture/sampler pairs that this function uses
     /// (directly or indirectly).
-    const utils::Vector<VariablePair, 8>& TextureSamplerPairs() const {
-        return texture_sampler_pairs_;
-    }
+    utils::VectorRef<VariablePair> TextureSamplerPairs() const { return texture_sampler_pairs_; }
 
     /// @returns the list of direct calls to functions / builtins made by this
     /// function
diff --git a/src/tint/sem/module.h b/src/tint/sem/module.h
index b451c5b..216a2c4 100644
--- a/src/tint/sem/module.h
+++ b/src/tint/sem/module.h
@@ -39,7 +39,7 @@
     ~Module() override;
 
     /// @returns the dependency-ordered global declarations for the module
-    const utils::Vector<const ast::Node*, 64>& DependencyOrderedDeclarations() const {
+    utils::VectorRef<const ast::Node*> DependencyOrderedDeclarations() const {
         return dep_ordered_decls_;
     }
 
diff --git a/src/tint/sem/struct.h b/src/tint/sem/struct.h
index 831cf3e..f878854 100644
--- a/src/tint/sem/struct.h
+++ b/src/tint/sem/struct.h
@@ -163,7 +163,7 @@
     /// @returns the conversion-rank ordered concrete versions of this abstract structure, or an
     /// empty vector if this structure is not abstract.
     /// @note only structures returned by builtins may be abstract (e.g. modf, frexp)
-    const utils::Vector<const Struct*, 2>& ConcreteTypes() const { return concrete_types_; }
+    utils::VectorRef<const Struct*> ConcreteTypes() const { return concrete_types_; }
 
   private:
     ast::Struct const* const declaration_;
diff --git a/src/tint/sem/type.cc b/src/tint/sem/type.cc
index 3d25e7e..51afc12 100644
--- a/src/tint/sem/type.cc
+++ b/src/tint/sem/type.cc
@@ -239,7 +239,7 @@
             return kNoConversion;
         },
         [&](const Struct* from_str) {
-            auto& concrete_tys = from_str->ConcreteTypes();
+            auto concrete_tys = from_str->ConcreteTypes();
             for (size_t i = 0; i < concrete_tys.Length(); i++) {
                 if (concrete_tys[i] == to) {
                     return static_cast<uint32_t>(i + 1);
diff --git a/src/tint/transform/direct_variable_access.cc b/src/tint/transform/direct_variable_access.cc
index d1c1339..26c4aba 100644
--- a/src/tint/transform/direct_variable_access.cc
+++ b/src/tint/transform/direct_variable_access.cc
@@ -228,7 +228,8 @@
         // will have the pointer parameters replaced with an array of u32s, used to perform the
         // pointer indexing in the variant.
         // Function call pointer arguments are replaced with an array of these dynamic indices.
-        for (auto* decl : utils::Reverse(sem.Module()->DependencyOrderedDeclarations())) {
+        auto decls = sem.Module()->DependencyOrderedDeclarations();
+        for (auto* decl : utils::Reverse(decls)) {
             if (auto* fn = sem.Get<sem::Function>(decl)) {
                 auto* fn_info = FnInfoFor(fn);
                 ProcessFunction(fn, fn_info);
diff --git a/src/tint/utils/transform.h b/src/tint/utils/transform.h
index 2faca46..d96a4bb 100644
--- a/src/tint/utils/transform.h
+++ b/src/tint/utils/transform.h
@@ -91,8 +91,7 @@
 /// @tparam N the small-array size of the returned Vector
 /// @returns a new vector with each element of the source vector transformed by `transform`.
 template <size_t N, typename IN, typename TRANSFORMER>
-auto Transform(const VectorRef<IN>& in, TRANSFORMER&& transform)
-    -> Vector<decltype(transform(in[0])), N> {
+auto Transform(VectorRef<IN> in, TRANSFORMER&& transform) -> Vector<decltype(transform(in[0])), N> {
     const auto count = in.Length();
     Vector<decltype(transform(in[0])), N> result;
     result.Reserve(count);
@@ -108,7 +107,7 @@
 /// @tparam N the small-array size of the returned Vector
 /// @returns a new vector with each element of the source vector transformed by `transform`.
 template <size_t N, typename IN, typename TRANSFORMER>
-auto Transform(const VectorRef<IN>& in, TRANSFORMER&& transform)
+auto Transform(VectorRef<IN> in, TRANSFORMER&& transform)
     -> Vector<decltype(transform(in[0], 1u)), N> {
     const auto count = in.Length();
     Vector<decltype(transform(in[0], 1u)), N> result;
diff --git a/src/tint/utils/unique_vector.h b/src/tint/utils/unique_vector.h
index bda090c..6cb8f88 100644
--- a/src/tint/utils/unique_vector.h
+++ b/src/tint/utils/unique_vector.h
@@ -87,8 +87,8 @@
     /// @returns an iterator to the end of the reversed vector
     auto rend() const { return vector.rend(); }
 
-    /// @returns a const reference to the internal vector
-    operator const Vector<T, N>&() const { return vector; }
+    /// @returns a reference to the internal vector
+    operator VectorRef<T>() const { return vector; }
 
     /// @returns the std::move()'d vector.
     /// @note The UniqueVector must not be used after calling this method
diff --git a/src/tint/utils/unique_vector_test.cc b/src/tint/utils/unique_vector_test.cc
index 9b015c2..c198615 100644
--- a/src/tint/utils/unique_vector_test.cc
+++ b/src/tint/utils/unique_vector_test.cc
@@ -94,11 +94,11 @@
     unique_vec.Add(1);
     unique_vec.Add(2);
 
-    const utils::Vector<int, 4>& vec = unique_vec;
-    EXPECT_EQ(vec.Length(), 3u);
+    utils::VectorRef<int> ref = unique_vec;
+    EXPECT_EQ(ref.Length(), 3u);
     EXPECT_EQ(unique_vec.IsEmpty(), false);
     int i = 0;
-    for (auto n : vec) {
+    for (auto n : ref) {
         EXPECT_EQ(n, i);
         i++;
     }
diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h
index 2371136..7e2c271 100644
--- a/src/tint/utils/vector.h
+++ b/src/tint/utils/vector.h
@@ -680,11 +680,11 @@
 Vector(Ts...) -> Vector<VectorCommonType<Ts...>, sizeof...(Ts)>;
 
 /// VectorRef is a weak reference to a Vector, used to pass vectors as parameters, avoiding copies
-/// between the caller and the callee. VectorRef can accept a Vector of any 'N' value, decoupling
-/// the caller's vector internal size from the callee's vector size. A VectorRef tracks the usage of
-/// moves either side of the call. If at the call site, a Vector argument is moved to a VectorRef
-/// parameter, and within the callee, the VectorRef parameter is moved to a Vector, then the Vector
-/// heap allocation will be moved. For example:
+/// between the caller and the callee, or as an non-static sized accessor on a vector. VectorRef can
+/// accept a Vector of any 'N' value, decoupling the caller's vector internal size from the callee's
+/// vector size. A VectorRef tracks the usage of moves either side of the call. If at the call site,
+/// a Vector argument is moved to a VectorRef parameter, and within the callee, the VectorRef
+/// parameter is moved to a Vector, then the Vector heap allocation will be moved. For example:
 ///
 /// ```
 ///     void func_a() {
@@ -698,6 +698,8 @@
 ///        Vector<std::string, 2> vec(std::move(vec_ref));
 ///     }
 /// ```
+///
+/// Aside from this move pattern, a VectorRef provides an immutable reference to the Vector.
 template <typename T>
 class VectorRef {
     /// The slice type used by this vector reference
@@ -710,6 +712,9 @@
     }
 
   public:
+    /// Type of `T`.
+    using value_type = T;
+
     /// Constructor - empty reference
     VectorRef() : slice_(EmptySlice()) {}
 
@@ -805,39 +810,21 @@
     bool IsEmpty() const { return slice_.len == 0; }
 
     /// @returns a reference to the first element in the vector
-    T& Front() { return slice_.Front(); }
-
-    /// @returns a reference to the first element in the vector
     const T& Front() const { return slice_.Front(); }
 
     /// @returns a reference to the last element in the vector
-    T& Back() { return slice_.Back(); }
-
-    /// @returns a reference to the last element in the vector
     const T& Back() const { return slice_.Back(); }
 
     /// @returns a pointer to the first element in the vector
-    T* begin() { return slice_.begin(); }
-
-    /// @returns a pointer to the first element in the vector
     const T* begin() const { return slice_.begin(); }
 
     /// @returns a pointer to one past the last element in the vector
-    T* end() { return slice_.end(); }
-
-    /// @returns a pointer to one past the last element in the vector
     const T* end() const { return slice_.end(); }
 
     /// @returns a reverse iterator starting with the last element in the vector
-    auto rbegin() { return slice_.rbegin(); }
-
-    /// @returns a reverse iterator starting with the last element in the vector
     auto rbegin() const { return slice_.rbegin(); }
 
     /// @returns the end for a reverse iterator
-    auto rend() { return slice_.rend(); }
-
-    /// @returns the end for a reverse iterator
     auto rend() const { return slice_.rend(); }
 
   private:
@@ -907,7 +894,7 @@
 /// @param vec the vector reference
 /// @return the std::ostream so calls can be chained
 template <typename T>
-inline std::ostream& operator<<(std::ostream& o, const utils::VectorRef<T>& vec) {
+inline std::ostream& operator<<(std::ostream& o, utils::VectorRef<T> vec) {
     o << "[";
     bool first = true;
     for (auto& el : vec) {
diff --git a/src/tint/utils/vector_test.cc b/src/tint/utils/vector_test.cc
index 74d15b7..ed9a97a 100644
--- a/src/tint/utils/vector_test.cc
+++ b/src/tint/utils/vector_test.cc
@@ -2073,15 +2073,6 @@
 
 TEST(TintVectorRefTest, FrontBack) {
     Vector<std::string, 3> vec{"front", "mid", "back"};
-    VectorRef<std::string> vec_ref(vec);
-    static_assert(!std::is_const_v<std::remove_reference_t<decltype(vec_ref.Front())>>);
-    static_assert(!std::is_const_v<std::remove_reference_t<decltype(vec_ref.Back())>>);
-    EXPECT_EQ(vec_ref.Front(), "front");
-    EXPECT_EQ(vec_ref.Back(), "back");
-}
-
-TEST(TintVectorRefTest, ConstFrontBack) {
-    Vector<std::string, 3> vec{"front", "mid", "back"};
     const VectorRef<std::string> vec_ref(vec);
     static_assert(std::is_const_v<std::remove_reference_t<decltype(vec_ref.Front())>>);
     static_assert(std::is_const_v<std::remove_reference_t<decltype(vec_ref.Back())>>);
@@ -2091,15 +2082,6 @@
 
 TEST(TintVectorRefTest, BeginEnd) {
     Vector<std::string, 3> vec{"front", "mid", "back"};
-    VectorRef<std::string> vec_ref(vec);
-    static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec_ref.begin())>>);
-    static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec_ref.end())>>);
-    EXPECT_EQ(vec_ref.begin(), &vec[0]);
-    EXPECT_EQ(vec_ref.end(), &vec[0] + 3);
-}
-
-TEST(TintVectorRefTest, ConstBeginEnd) {
-    Vector<std::string, 3> vec{"front", "mid", "back"};
     const VectorRef<std::string> vec_ref(vec);
     static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec_ref.begin())>>);
     static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec_ref.end())>>);
diff --git a/src/tint/writer/spirv/builder_type_test.cc b/src/tint/writer/spirv/builder_type_test.cc
index 4377c42..4ab8aa0 100644
--- a/src/tint/writer/spirv/builder_type_test.cc
+++ b/src/tint/writer/spirv/builder_type_test.cc
@@ -442,8 +442,8 @@
     auto* arr_arr_mat2x3_f32 =
         ty.array(ty.array(ty.mat2x3<f32>(), 1_u), 2_u);  // Doubly nested array
     auto* arr_arr_mat2x3_f16 =
-        ty.array(ty.array(ty.mat2x3<f16>(), 1_u), 2_u);      // Doubly nested array
-    auto* rtarr_mat4x4 = ty.array(ty.mat4x4<f32>());         // Runtime array
+        ty.array(ty.array(ty.mat2x3<f16>(), 1_u), 2_u);  // Doubly nested array
+    auto* rtarr_mat4x4 = ty.array(ty.mat4x4<f32>());     // Runtime array
 
     auto* s = Structure(
         "S", utils::Vector{