[tint][utils] Allow assignment of Slice to Vector

Some IR methods now return slices, and this makes it easier to copy
them around.

Change-Id: Iaa3a7180c7baf4535a18d39a4d0404543f650a6b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/136460
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h
index 29ff218..5cb0ff3 100644
--- a/src/tint/utils/vector.h
+++ b/src/tint/utils/vector.h
@@ -133,6 +133,10 @@
     /// @param other the vector reference to copy
     Vector(const VectorRef<T>& other) { Copy(other.slice_); }  // NOLINT(runtime/explicit)
 
+    /// Copy constructor from an immutable slice
+    /// @param other the slice to copy
+    Vector(const Slice<T>& other) { Copy(other); }  // NOLINT(runtime/explicit)
+
     /// Destructor
     ~Vector() { ClearAndFree(); }
 
@@ -194,6 +198,14 @@
         return *this;
     }
 
+    /// Assignment operator for Slice
+    /// @param other the slice to copy
+    /// @returns this vector so calls can be chained
+    Vector& operator=(const Slice<T>& other) {
+        Copy(other);
+        return *this;
+    }
+
     /// Index operator
     /// @param i the element index. Must be less than `len`.
     /// @returns a reference to the i'th element.
diff --git a/src/tint/utils/vector_test.cc b/src/tint/utils/vector_test.cc
index c9d4481..31e1a86 100644
--- a/src/tint/utils/vector_test.cc
+++ b/src/tint/utils/vector_test.cc
@@ -1106,6 +1106,54 @@
     EXPECT_TRUE(AllExternallyHeld(vec));
 }
 
+TEST(TintVectorTest, CopyAssignSlice_N2_to_N2) {
+    std::string data[] = {"hello", "world"};
+    Slice<std::string> slice(data);
+    Vector<std::string, 2> vec_b;
+    vec_b = slice;
+    EXPECT_EQ(vec_b.Length(), 2u);
+    EXPECT_EQ(vec_b.Capacity(), 2u);
+    EXPECT_EQ(vec_b[0], "hello");
+    EXPECT_EQ(vec_b[1], "world");
+    EXPECT_TRUE(AllInternallyHeld(vec_b));
+}
+
+TEST(TintVectorTest, CopyAssignSlice_N2_to_N1) {
+    std::string data[] = {"hello", "world"};
+    Slice<std::string> slice(data);
+    Vector<std::string, 1> vec_b;
+    vec_b = slice;
+    EXPECT_EQ(vec_b.Length(), 2u);
+    EXPECT_EQ(vec_b.Capacity(), 2u);
+    EXPECT_EQ(vec_b[0], "hello");
+    EXPECT_EQ(vec_b[1], "world");
+    EXPECT_TRUE(AllExternallyHeld(vec_b));
+}
+
+TEST(TintVectorTest, CopyAssignSlice_N2_to_N3) {
+    std::string data[] = {"hello", "world"};
+    Slice<std::string> slice(data);
+    Vector<std::string, 3> vec_b;
+    vec_b = slice;
+    EXPECT_EQ(vec_b.Length(), 2u);
+    EXPECT_EQ(vec_b.Capacity(), 3u);
+    EXPECT_EQ(vec_b[0], "hello");
+    EXPECT_EQ(vec_b[1], "world");
+    EXPECT_TRUE(AllInternallyHeld(vec_b));
+}
+
+TEST(TintVectorTest, CopyAssignSlice_N2_to_N0) {
+    std::string data[] = {"hello", "world"};
+    Slice<std::string> slice(data);
+    Vector<std::string, 0> vec_b;
+    vec_b = slice;
+    EXPECT_EQ(vec_b.Length(), 2u);
+    EXPECT_EQ(vec_b.Capacity(), 2u);
+    EXPECT_EQ(vec_b[0], "hello");
+    EXPECT_EQ(vec_b[1], "world");
+    EXPECT_TRUE(AllExternallyHeld(vec_b));
+}
+
 TEST(TintVectorTest, Index) {
     Vector<std::string, 2> vec{"hello", "world"};
     static_assert(!std::is_const_v<std::remove_reference_t<decltype(vec[0])>>);