spirv-val: Better error message when types are the same (#6427)

> OpAccessChain result type (OpTypeInt) does not match the type that
results from indexing into the base <id> (OpTypeInt).

This was confusing, Ideally we could print out the 2 `OpTypeInt`, but
for a short "better quality of life" fix, just made the message point
out what is likely going on
diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp
index 1225722..d33c3c2 100644
--- a/source/val/validate_memory.cpp
+++ b/source/val/validate_memory.cpp
@@ -1847,13 +1847,19 @@
     // At this point, we have fully walked down from the base using the indeces.
     // The type being pointed to should be the same as the result type.
     if (type_pointee->id() != result_type_pointee->id()) {
+      bool same_type = result_type_pointee->opcode() == type_pointee->opcode();
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "Op" << spvOpcodeString(opcode) << " result type (Op"
+             << "Op" << spvOpcodeString(opcode) << " result type <id> "
+             << _.getIdName(result_type_pointee->id()) << " (Op"
              << spvOpcodeString(result_type_pointee->opcode())
              << ") does not match the type that results from indexing into the "
                 "base "
-                "<id> (Op"
-             << spvOpcodeString(type_pointee->opcode()) << ").";
+                "<id> "
+             << _.getIdName(type_pointee->id()) << " (Op"
+             << spvOpcodeString(type_pointee->opcode()) << ")."
+             << (same_type ? " (The types must be the exact same Id, so the "
+                             "two types referenced are slighlty different)"
+                           : "");
     }
   }
 
diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp
index 20f6560..0fc3aea 100644
--- a/test/val/val_id_test.cpp
+++ b/test/val/val_id_test.cpp
@@ -4176,10 +4176,46 @@
   getValidatorOptions()->relax_logical_pointer = true;
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("result type (OpTypeMatrix) does not match the type that "
-                "results from indexing into the base <id> (OpTypeFloat)."));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("result type <id> '6[%mat4v3float]' (OpTypeMatrix) "
+                        "does not match the type that results from indexing "
+                        "into the base <id> '4[%float]' (OpTypeFloat)"));
+}
+
+TEST_P(AccessChainInstructionTest, AccessChainDifferentIntTypes) {
+  std::string spirv = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main" %_
+               OpExecutionMode %main LocalSize 1 1 1
+               OpDecorate %_arr_uint_uint_32 ArrayStride 4
+               OpDecorate %SSBO Block
+               OpMemberDecorate %SSBO 0 Offset 0
+               OpDecorate %_ Binding 0
+               OpDecorate %_ DescriptorSet 0
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+       %uint = OpTypeInt 32 0
+    %uint_32 = OpConstant %uint 32
+%_arr_uint_uint_32 = OpTypeArray %uint %uint_32
+       %SSBO = OpTypeStruct %_arr_uint_uint_32
+%_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO
+          %_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+     %uint_1 = OpConstant %uint 1
+%ptr_ssbo_int = OpTypePointer StorageBuffer %int
+       %main = OpFunction %void None %4
+          %6 = OpLabel
+         %18 = OpAccessChain %ptr_ssbo_int %_ %int_0 %int_0
+               OpReturn
+               OpFunctionEnd
+  )";
+  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_3);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_3));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("The types must be the exact same Id, so the two types "
+                        "referenced are slighlty different"));
 }
 
 // Valid: 255 indexes passed to the access chain instruction. Limit is 255.
@@ -4375,10 +4411,11 @@
 OpReturn
 OpFunctionEnd
   )";
-  const std::string expected_err = instr +
-                                   " result type (OpTypeFloat) does not match "
-                                   "the type that results from indexing into "
-                                   "the base <id> (OpTypeVector).";
+  const std::string expected_err =
+      instr +
+      " result type <id> '4[%float]' (OpTypeFloat) does not match the type "
+      "that results from indexing into the base <id> '18[%v4float]' "
+      "(OpTypeVector).";
   getValidatorOptions()->relax_logical_pointer = true;
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
@@ -4532,10 +4569,11 @@
 OpReturn
 OpFunctionEnd
   )";
-  const std::string expected_err = instr +
-                                   " result type (OpTypeMatrix) does not match "
-                                   "the type that results from indexing into "
-                                   "the base <id> (OpTypeFloat).";
+  const std::string expected_err =
+      instr +
+      " result type <id> '6[%mat4v3float]' (OpTypeMatrix) does not match the "
+      "type that results from indexing into the base <id> '4[%float]' "
+      "(OpTypeFloat).";
   getValidatorOptions()->relax_logical_pointer = true;
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());