Validator: thread table limits through `OnReturnCallIndirect` (#2744)

`SharedValidator::OnCallIndirect` passes `table_type.limits` to
`TypeChecker::OnCallIndirect`, which expects i64 vs i32 for the
table-index based on `is_64`. `OnReturnCallIndirect` doesn't — so under
`table64`, plain `call_indirect` with an i64 index validates, but the
matching `return_call_indirect` rejects it with `expected [i32] but got
[i64]`.

Mirrors the signature. Adds a `test/typecheck/` regression for the
negative case.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h
index 25b2a42..1033b5b 100644
--- a/include/wabt/type-checker.h
+++ b/include/wabt/type-checker.h
@@ -106,7 +106,8 @@
   Result OnReturnCall(const TypeVector& param_types,
                       const TypeVector& result_types);
   Result OnReturnCallIndirect(const TypeVector& param_types,
-                              const TypeVector& result_types);
+                              const TypeVector& result_types,
+                              const Limits& table_limits);
   Result OnReturnCallRef(Type type,
                          const TypeVector& param_types,
                          const TypeVector& result_types);
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index b7b748e..243b653 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -1225,8 +1225,8 @@
                          "type mismatch: return_call_indirect must reference "
                          "table of funcref type");
   }
-  result |=
-      typechecker_.OnReturnCallIndirect(func_type.params, func_type.results);
+  result |= typechecker_.OnReturnCallIndirect(
+      func_type.params, func_type.results, table_type.limits);
   IgnoreLocalRefs();
   return result;
 }
diff --git a/src/type-checker.cc b/src/type-checker.cc
index bb0e4d7..e309190 100644
--- a/src/type-checker.cc
+++ b/src/type-checker.cc
@@ -722,8 +722,10 @@
 }
 
 Result TypeChecker::OnReturnCallIndirect(const TypeVector& param_types,
-                                         const TypeVector& result_types) {
-  Result result = PopAndCheck1Type(Type::I32, "return_call_indirect");
+                                         const TypeVector& result_types,
+                                         const Limits& table_limits) {
+  Result result = PopAndCheck1Type(table_limits.is_64 ? Type::I64 : Type::I32,
+                                   "return_call_indirect");
 
   result |= PopAndCheckSignature(param_types, "return_call_indirect");
   result |= PopAndCheckReturnCall(result_types, "return_call_indirect");
diff --git a/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt b/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt
new file mode 100644
index 0000000..940c333
--- /dev/null
+++ b/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt
@@ -0,0 +1,16 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-tail-call --enable-memory64
+;;; ERROR: 1
+(module
+  (type $t (func))
+  (func $f)
+  (table i64 1 1 funcref)
+  (elem (i64.const 0) $f)
+  (func
+    i32.const 0
+    return_call_indirect (type $t)))
+(;; STDERR ;;;
+out/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt:11:5: error: type mismatch in return_call_indirect, expected [i64] but got [i32]
+    return_call_indirect (type $t)))
+    ^^^^^^^^^^^^^^^^^^^^
+;;; STDERR ;;)