Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-16 Thread via GitHub


tqchen merged PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on code in PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#discussion_r2810496986


##
src/ffi/extra/reflection_extra.cc:
##
@@ -133,11 +134,46 @@ inline void AccessPathRegisterReflection() {
[](const AccessPath& self, const AccessPath& other) { return 
self->PathEqual(other); });
 }
 
+int64_t StructuralKeyHash(const Any& key) {
+  const auto* key_obj = key.as();
+  TVM_FFI_ICHECK_NOTNULL(key_obj);
+  return key_obj->hash_i64;
+}
+
+bool StructuralKeyEqual(const Any& lhs, const Any& rhs) {
+  if (lhs.same_as(rhs)) {
+return true;
+  }
+  const auto* lhs_obj = lhs.as();
+  const auto* rhs_obj = rhs.as();
+  TVM_FFI_ICHECK_NOTNULL(lhs_obj);
+  TVM_FFI_ICHECK_NOTNULL(rhs_obj);
+  if (lhs_obj->hash_i64 != rhs_obj->hash_i64) {
+return false;
+  }
+  return StructuralEqual::Equal(lhs_obj->key, rhs_obj->key);
+}
+
+inline void StructuralKeyRegisterReflection() {
+  namespace refl = tvm::ffi::reflection;
+  refl::ObjectDef()
+  .def_ro("key", &StructuralKeyObj::key)
+  .def_ro("hash_i64", &StructuralKeyObj::hash_i64);
+  refl::TypeAttrDef()
+  .attr("__any_hash__", reinterpret_cast(&StructuralKeyHash))
+  .attr("__any_equal__", reinterpret_cast(&StructuralKeyEqual));
+}
+
 TVM_FFI_STATIC_INIT_BLOCK() {
   namespace refl = tvm::ffi::reflection;
   AccessStepRegisterReflection();
   AccessPathRegisterReflection();
-  refl::GlobalDef().def_packed("ffi.MakeObjectFromPackedArgs", 
MakeObjectFromPackedArgs);
+  StructuralKeyRegisterReflection();
+
+  refl::GlobalDef()
+  .def_packed("ffi.MakeObjectFromPackedArgs", MakeObjectFromPackedArgs)
+  .def("ffi.StructuralKey", [](Any key) { return 
StructuralKey(std::move(key)); })
+  .def("ffi.StructuralKeyEqual", StructuralKeyEqual);

Review Comment:
   ![high](https://www.gstatic.com/codereviewagent/high-priority.svg)
   
   The FFI function `StructuralKeyHash` is declared in 
`python/tvm_ffi/_ffi_api.py` but it's not registered as a global function here. 
This will cause a runtime error if `tvm_ffi._ffi_api.StructuralKeyHash` is 
called from Python. Please register it to match the Python API definition.
   
   ```c
 .def("ffi.StructuralKeyEqual", StructuralKeyEqual)
 .def("ffi.StructuralKeyHash", StructuralKeyHash);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


tqchen commented on PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#issuecomment-3906235487

   
   /gemini review
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on code in PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#discussion_r2810484670


##
include/tvm/ffi/extra/structural_key.h:
##
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*!
+ * \file tvm/ffi/extra/structural_key.h
+ * \brief Structural-key wrapper that caches structural hash.
+ */
+#ifndef TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+#define TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+namespace tvm {
+namespace ffi {
+
+/*!
+ * \brief Object node that contains a key and its cached structural hash.
+ */
+class StructuralKeyObj : public Object {
+ public:
+  /*! \brief The key value. */
+  Any key;
+  /*! \brief Cached structural hash of \p key, encoded as int64_t. */
+  int64_t hash_i64;
+
+  // Default constructor to support reflection-based initialization.
+  StructuralKeyObj() = default;
+  /*!
+   * \brief Construct a StructuralKeyObj from a key and cache its structural 
hash.
+   * \param key The key value.
+   */
+  explicit StructuralKeyObj(Any key)
+  : key(std::move(key)), 
hash_i64(static_cast(StructuralHash::Hash(this->key))) {}
+
+  /// \cond Doxygen_Suppress
+  TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ffi.StructuralKey", StructuralKeyObj, 
Object);
+  /// \endcond
+};
+
+/*!
+ * \brief ObjectRef wrapper for StructuralKeyObj.
+ *
+ * StructuralKey can be used to ensure that we use structural equality and 
hash for the wrapped key.
+ */
+class StructuralKey : public ObjectRef {
+ public:
+  /*!
+   * \brief Construct a StructuralKey from a key.
+   * \param key The key value.
+   */
+  explicit StructuralKey(Any key) : 
ObjectRef(make_object(std::move(key))) {}
+
+  bool operator==(const StructuralKey& other) const {
+if (this->same_as(other)) {
+  return true;
+}
+if (this->get()->hash_i64 != other->hash_i64) {
+  return false;
+}
+return StructuralEqual::Equal(this->get()->key, other->key);
+  }

Review Comment:
   ![high](https://www.gstatic.com/codereviewagent/high-priority.svg)
   
   Since `StructuralKey` is an `ObjectRef`, it inherits `operator!=` from the 
base class, which performs pointer inequality. By overriding `operator==` to 
use structural equality without also overriding `operator!=`, you create an 
inconsistency where `k1 == k2` might be true (structurally) but `k1 != k2` 
could also be true (different pointers). You should explicitly define 
`operator!=` to maintain consistency.
   
   ```suggestion
 bool operator==(const StructuralKey& other) const {
   if (this->same_as(other)) {
 return true;
   }
   if (this->get()->hash_i64 != other->hash_i64) {
 return false;
   }
   return StructuralEqual::Equal(this->get()->key, other->key);
 }
   
 bool operator!=(const StructuralKey& other) const {
   return !(*this == other);
 }
   ```



##
include/tvm/ffi/extra/structural_key.h:
##
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*!
+ * \file tvm/ffi/extra/structural_key.h
+ * \brief Structural-key wrapper that caches structural hash.
+ */
+#ifndef TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+#define TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+namespace tvm {
+namespace ffi {
+
+/*!
+ * \brief Object node that contains a key and its cac

Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


tqchen commented on PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#issuecomment-3906208978

   
   /gemini review
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on code in PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#discussion_r2810474060


##
src/ffi/extra/reflection_extra.cc:
##
@@ -133,11 +134,42 @@ inline void AccessPathRegisterReflection() {
[](const AccessPath& self, const AccessPath& other) { return 
self->PathEqual(other); });
 }
 
+int64_t StructuralKeyHash(const Any& key) { return 
key.cast()->hash_i64; }

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   For better performance and consistency with `StructuralKeyEqual`, consider 
using `as()` instead of `cast()`. `cast` 
creates a temporary `ObjectRef` which involves reference counting overhead, 
while `as` provides a direct pointer without this overhead. Given that this 
function is an `__any_hash__` hook, the `key` is guaranteed to be of the 
correct type, so a direct `as` is safe.
   
   ```suggestion
   int64_t StructuralKeyHash(const Any& key) { return 
key.as()->hash_i64; }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


tqchen commented on PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#issuecomment-3906202507

   
   /gemini review
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on code in PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#discussion_r2810467921


##
src/ffi/extra/reflection_extra.cc:
##
@@ -133,11 +134,40 @@ inline void AccessPathRegisterReflection() {
[](const AccessPath& self, const AccessPath& other) { return 
self->PathEqual(other); });
 }
 
+int64_t StructuralKeyHash(const Any& key) { return 
key.cast()->hash_i64; }
+
+bool StructuralKeyEqual(const Any& lhs, const Any& rhs) {
+  auto lhs_key = lhs.try_cast();
+  auto rhs_key = rhs.try_cast();
+  if (!lhs_key.has_value() || !rhs_key.has_value()) {
+return false;
+  }
+  if ((*lhs_key)->hash_i64 != (*rhs_key)->hash_i64) {
+return false;
+  }
+  return StructuralEqual::Equal((*lhs_key)->key, (*rhs_key)->key);
+}

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   For improved efficiency and correctness, this function can be optimized. 
Since it's registered as the `__any_equal__` handler for `StructuralKey`, we 
can assume that `lhs` and `rhs` are of type `StructuralKey`. Using 
`as()` is more direct and avoids the overhead of 
`try_cast()`, which creates temporary `ObjectRef`s. 
Additionally, including a `same_as` check at the beginning is a beneficial 
optimization for when the two objects are the same instance.
   
   ```suggestion
   bool StructuralKeyEqual(const Any& lhs, const Any& rhs) {
 if (lhs.same_as(rhs)) {
   return true;
 }
 const auto* lhs_obj = lhs.as();
 const auto* rhs_obj = rhs.as();
 if (lhs_obj->hash_i64 != rhs_obj->hash_i64) {
   return false;
 }
 return StructuralEqual::Equal(lhs_obj->key, rhs_obj->key);
   }
   ```



##
python/tvm_ffi/structural.py:
##
@@ -0,0 +1,230 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# pylint: disable=invalid-name
+"""Structural helper objects and functions."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
+
+if TYPE_CHECKING:
+from .access_path import AccessPath
+
+from . import _ffi_api
+from .core import Object
+from .registry import register_object
+
+__all__ = [
+"StructuralKey",
+"get_first_structural_mismatch",
+"structural_equal",
+"structural_hash",
+]
+
+
+def structural_equal(
+lhs: Any, rhs: Any, map_free_vars: bool = False, skip_tensor_content: bool 
= False
+) -> bool:
+"""Check structural equality between two values.
+
+Structural equality compares the *shape/content structure* of two values
+instead of Python object identity. For container-like values, this means
+recursive comparison of elements/fields. For object types that provide
+structural equal hooks, those hooks are used.
+
+Parameters
+--
+lhs
+Left-hand side value.
+rhs
+Right-hand side value.
+
+map_free_vars
+Whether free variables (variables without a definition site) can be
+mapped to each other during comparison.
+
+skip_tensor_content
+Whether to skip tensor data content when comparing tensors.
+
+Returns
+---
+result
+Whether the two values are structurally equal.
+
+Examples
+
+.. code-block:: python
+
+import tvm_ffi
+
+assert tvm_ffi.structural_equal([1, 2, 3], [1, 2, 3])
+assert not tvm_ffi.structural_equal([1, 2, 3], [1, 2, 4])
+
+See Also
+
+:py:func:`tvm_ffi.structural_hash`
+Hash function compatible with structural equality.
+:py:func:`tvm_ffi.get_first_structural_mismatch`
+Mismatch diagnostics with access paths.
+
+"""
+return _ffi_api.StructuralEqual(lhs, rhs, map_free_vars, 
skip_tensor_content)
+
+
+def structural_hash(
+value: Any, map_free_vars: bool = False, skip_tensor_content: bool = False
+) -> int:
+"""Compute structural hash of a value.
+
+This hash is designed to be consistent with :py:func:`structural_equal`
+under the same options. If two values are structurally equal, they should
+have the same structural hash.
+
+Parameters
+--
+value
+Input value to hash.
+
+map_free_vars
+Whether free variables mapped to each oth

Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


tqchen commented on PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#issuecomment-3906193984

   /gemini review


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on code in PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#discussion_r2810450038


##
include/tvm/ffi/extra/structural_key.h:
##
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*!
+ * \file tvm/ffi/extra/structural_key.h
+ * \brief Structural-key wrapper that caches structural hash.
+ */
+#ifndef TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+#define TVM_FFI_EXTRA_STRUCTURAL_KEY_H_
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+namespace tvm {
+namespace ffi {
+
+/*!
+ * \brief Object node that contains a key and its cached structural hash.
+ */
+class StructuralKeyObj : public Object {
+ public:
+  /*! \brief The key value. */
+  Any key;
+  /*! \brief Cached structural hash of \p key, encoded as int64_t. */
+  int64_t hash_i64;
+
+  // Default constructor to support reflection-based initialization.
+  StructuralKeyObj() = default;
+  explicit StructuralKeyObj(Any key)
+  : key(std::move(key)), 
hash_i64(static_cast(StructuralHash::Hash(this->key))) {}

Review Comment:
   ![critical](https://www.gstatic.com/codereviewagent/critical.svg)
   
   The `StructuralKeyObj` constructor computes the structural hash using 
default arguments for `StructuralHash::Hash`, which means 
`skip_tensor_content=false`. However, both `StructuralKey::operator==` (line 
72) and `ffi::StructuralKeyEqual` (in `src/ffi/extra/reflection_extra.cc`) use 
`StructuralEqual::Equal` with `skip_tensor_content=true`.
   
   This inconsistency violates the contract that if two objects are equal, 
their hashes must also be equal. For two `StructuralKey` objects wrapping 
tensors with the same shape but different content, the equality comparison 
would consider them equal (since `skip_tensor_content=true`), but their cached 
hashes would be different. This would lead to incorrect behavior in hash-based 
containers like `std::unordered_map` or `tvm::Map`.
   
   To fix this, the hash should be computed with the same `skip_tensor_content` 
policy as the equality check.
   
   ```suggestion
 : key(std::move(key)), 
hash_i64(static_cast(StructuralHash::Hash(this->key, 
/*map_free_vars=*/false, /*skip_tensor_content=*/true))) {}
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


-
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Re: [PR] [EXTRA] Introduce StructuralKey [tvm-ffi]

2026-02-15 Thread via GitHub


gemini-code-assist[bot] commented on PR #453:
URL: https://github.com/apache/tvm-ffi/pull/453#issuecomment-3906172584

   ## Summary of Changes
   
   Hello @tqchen, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull 
request and will post my feedback shortly. In the meantime, here's a summary to 
help you and other reviewers quickly get up to speed!
   
   This pull request introduces the `StructuralKey` wrapper class, which 
provides a convenient mechanism to enforce structural equality and hashing for 
arbitrary `Any` objects. By caching the structural hash and overriding 
comparison operators, `StructuralKey` enables the use of complex data 
structures as keys in hash-based containers, such as `std::unordered_map` in 
C++ or Python dictionaries, where comparison is based on content rather than 
object identity. This enhancement improves the flexibility and utility of the 
FFI system for managing and comparing objects with deep structural semantics.
   
   ### Highlights
   
   * **New StructuralKey Class**: Introduced a new C++ `StructuralKey` class 
and its `ObjectRef` wrapper, designed to encapsulate an `Any` type and cache 
its structural hash, facilitating structural equality comparisons.
   * **Structural Equality and Hashing**: Implemented `operator==` for 
`StructuralKey` to perform structural equality checks and provided a 
`std::hash` specialization, enabling `StructuralKey` to be used as keys in C++ 
standard hash-based containers like `std::unordered_map`.
   * **Python Bindings and Helpers**: Exposed `StructuralKey` and related 
structural equality/hashing functions (`structural_equal`, `structural_hash`, 
`get_first_structural_mismatch`) to the Python `tvm_ffi` module, allowing 
Python users to leverage structural semantics for object comparison and hashing.
   * **Reflection and FFI Integration**: Integrated `StructuralKey` into the 
FFI reflection system, registering its object definition and type attributes, 
and exposing its constructor and equality comparison through FFI APIs for 
seamless C++ and Python interoperability.
   * **Comprehensive Testing**: Added dedicated C++ and Python unit tests to 
validate the correctness of `StructuralKey`'s equality, hashing, and its 
behavior when used in both C++ `std::unordered_map` and Python 
dictionaries/`tvm_ffi.Map`.
   
   🧠 **New Feature in Public Preview:** You can now enable **Memory** to help 
**Gemini Code Assist** learn from your team's feedback. This makes future code 
reviews more consistent and personalized to your project's style. **Click 
[here](https://codeassist.google/code-review/login) to enable Memory in your 
admin console.**
   
   
   Changelog
   
   * **include/tvm/ffi/extra/structural_key.h**
   * Added `StructuralKeyObj` and `StructuralKey` classes for structural 
hashing and equality.
   * Implemented `operator==` for `StructuralKey` to perform structural 
comparisons.
   * Provided a `std::hash` specialization for `StructuralKey` to enable 
its use in hash tables.
   * **python/tvm_ffi/__init__.py**
   * Imported `StructuralKey` and structural helper functions 
(`get_first_structural_mismatch`, `structural_equal`, `structural_hash`).
   * Added `StructuralKey` and structural helper functions to the module's 
`__all__` export list.
   * **python/tvm_ffi/_ffi_api.py**
   * Added FFI definitions for `StructuralKey`, `StructuralKeyEqual`, 
`StructuralKeyHash`, and `StructuralEqual`.
   * **python/tvm_ffi/structural.py**
   * Added new file defining Python functions `structural_equal`, 
`structural_hash`, and `get_first_structural_mismatch`.
   * Implemented the Python `StructuralKey` class with `__init__`, 
`__hash__`, and `__eq__` methods, leveraging C++ FFI.
   * **src/ffi/extra/reflection_extra.cc**
   * Included `tvm/ffi/extra/structural_key.h`.
   * Registered `StructuralKeyObj` for reflection, exposing its `key` and 
`hash_i64` members.
   * Defined `StructuralKeyHash` and `StructuralKeyEqual` functions for FFI.
   * Exposed `ffi.StructuralKey` constructor and `ffi.StructuralKeyEqual` 
via FFI.
   * **src/ffi/extra/structural_equal.cc**
   * Exposed `ffi.StructuralEqual` via FFI.
   * **tests/cpp/extra/test_structural_key.cc**
   * Added new C++ unit tests for `StructuralKey` covering equality, 
`std::hash` behavior, and usage in `std::unordered_map`.
   * **tests/python/test_structural.py**
   * Added new Python unit tests for `StructuralKey` and structural helper 
functions.
   * Verified `StructuralKey` behavior in Python dictionaries and 
`tvm_ffi.Map`.
   
   
   
   Using Gemini Code Assist
   
   
   The full guide for Gemini Code Assist can be found on our [documentation 
page](https://developers.google.com/gemini-code-assist/docs/review-github-code),
 here are some quick tips.
   
   Invoking Gemini
   
   You can request assistance from Gemini at any point by creating a comment 
using either `/gemini ` or `@gemini-code-assist `