[tint] Add binding_array indexing to the resolver.

Bug: 393558555
Change-Id: Ia4f4227c8ba509576621867e355957ff7f99eb1f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/229174
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/constant/eval_indexing_test.cc b/src/tint/lang/core/constant/eval_indexing_test.cc
index 8583390..f45ccbd 100644
--- a/src/tint/lang/core/constant/eval_indexing_test.cc
+++ b/src/tint/lang/core/constant/eval_indexing_test.cc
@@ -319,6 +319,30 @@
     EXPECT_EQ(r()->error(), "12:34 error: index -2 out of bounds");
 }
 
+TEST_F(ConstEvalTest, BindingArray_Index_OOB_Low) {
+    GlobalVar(
+        "a", Binding(0_a), Group(0_a),
+        ty("binding_array", ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()), 4_u));
+    auto* acc = IndexAccessor("a", Expr(Source{{12, 34}}, -1_i));
+    auto* call = Call("textureDimensions", acc);
+    WrapInFunction(call);
+
+    EXPECT_FALSE(r()->Resolve()) << r()->error();
+    EXPECT_EQ(r()->error(), "12:34 error: index -1 out of bounds [0..3]");
+}
+
+TEST_F(ConstEvalTest, BindingArray_Index_OOB_High) {
+    GlobalVar(
+        "a", Binding(0_a), Group(0_a),
+        ty("binding_array", ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()), 4_u));
+    auto* acc = IndexAccessor("a", Expr(Source{{12, 34}}, 4_i));
+    auto* call = Call("textureDimensions", acc);
+    WrapInFunction(call);
+
+    EXPECT_FALSE(r()->Resolve()) << r()->error();
+    EXPECT_EQ(r()->error(), "12:34 error: index 4 out of bounds [0..3]");
+}
+
 TEST_F(ConstEvalTest, ChainedIndex) {
     auto* arr_expr = Call<array<mat2x3<f32>, 2>>(           //
         Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f),   //
diff --git a/src/tint/lang/wgsl/resolver/array_accessor_test.cc b/src/tint/lang/wgsl/resolver/array_accessor_test.cc
index b3e98ed..fbbc9a8 100644
--- a/src/tint/lang/wgsl/resolver/array_accessor_test.cc
+++ b/src/tint/lang/wgsl/resolver/array_accessor_test.cc
@@ -198,6 +198,68 @@
     EXPECT_EQ(idx_sem->Object()->Declaration(), acc->object);
 }
 
+TEST_F(ResolverIndexAccessorTest, BindingArray_F32) {
+    GlobalVar(
+        "a", Binding(0_a), Group(0_a),
+        ty("binding_array", ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()), 4_u));
+    auto* acc = IndexAccessor("a", Expr(Source{{12, 34}}, 2_f));
+    auto* call = Call("textureDimensions", acc);
+    WrapInFunction(call);
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(), "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
+}
+
+TEST_F(ResolverIndexAccessorTest, BindingArray_Literal_i32) {
+    GlobalVar(
+        "a", Binding(0_a), Group(0_a),
+        ty("binding_array", ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()), 4_u));
+    auto* acc = IndexAccessor("a", 2_i);
+    auto* call = Call("textureDimensions", acc);
+    WrapInFunction(call);
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+    ASSERT_NE(TypeOf(acc), nullptr);
+    EXPECT_TRUE(TypeOf(acc)->Is<core::type::SampledTexture>());
+    ASSERT_TRUE(TypeOf(acc)->As<core::type::SampledTexture>()->Type()->Is<core::type::F32>());
+    ASSERT_EQ(TypeOf(acc)->As<core::type::SampledTexture>()->Dim(),
+              core::type::TextureDimension::k2d);
+
+    auto idx_sem = Sem().Get(acc)->UnwrapLoad()->As<sem::IndexAccessorExpression>();
+    ASSERT_NE(idx_sem, nullptr);
+    EXPECT_EQ(idx_sem->Index()->Declaration(), acc->index);
+    EXPECT_EQ(idx_sem->Object()->Declaration(), acc->object);
+}
+
+TEST_F(ResolverIndexAccessorTest, BindingArray_Dynamic_i32) {
+    GlobalVar(
+        "a", Binding(0_a), Group(0_a),
+        ty("binding_array", ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()), 4_u));
+    auto* idx = Var("idx", ty.i32(), Call<i32>());
+    auto* acc = IndexAccessor("a", idx);
+    auto* call = Call("textureDimensions", acc);
+    auto* f = Var("f", call);
+    Func("my_func", tint::Empty, ty.void_(),
+         Vector{
+             Decl(idx),
+             Decl(f),
+         });
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+    ASSERT_NE(TypeOf(acc), nullptr);
+    EXPECT_TRUE(TypeOf(acc)->Is<core::type::SampledTexture>());
+    ASSERT_TRUE(TypeOf(acc)->As<core::type::SampledTexture>()->Type()->Is<core::type::F32>());
+    ASSERT_EQ(TypeOf(acc)->As<core::type::SampledTexture>()->Dim(),
+              core::type::TextureDimension::k2d);
+
+    auto idx_sem = Sem().Get(acc)->UnwrapLoad()->As<sem::IndexAccessorExpression>();
+    ASSERT_NE(idx_sem, nullptr);
+    EXPECT_EQ(idx_sem->Index()->Declaration(), acc->index);
+    EXPECT_EQ(idx_sem->Object()->Declaration(), acc->object);
+}
+
 TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) {
     GlobalVar("my_var", ty.array<f32, 3>(), core::AddressSpace::kPrivate);
     auto* acc = IndexAccessor("my_var", 2_i);
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 09abd13..5e5c029 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -2027,6 +2027,7 @@
     auto* ty = Switch(
         storage_ty,  //
         [&](const sem::Array* arr) { return arr->ElemType(); },
+        [&](const core::type::BindingArray* arr) { return arr->ElemType(); },
         [&](const core::type::Vector* vec) { return vec->Type(); },
         [&](const core::type::Matrix* mat) {
             return b.create<core::type::Vector>(mat->Type(), mat->Rows());