Lunderberg opened a new pull request, #15672:
URL: https://github.com/apache/tvm/pull/15672

   This commit introduces a new container, `Variant`, which is analogous to the 
`std::variant` introduced in C++17, the `enum` in Rust, or a tagged union in C. 
 The `Variant` class is templated over the types that it may contain (e.g. 
`Variant<String, Expr>`), where each type is a distinct option that can be 
stored within the container.
   
   `Variant` is implemented as a subclass of `ObjectRef` with no additional 
data members, similar to the implementation of `Optional<T>`.  It can be 
constructed from any of its contained types, and the contents can be inspected 
using the usual `my_object.as<T>()` and `Downcast<T>(my_object)` methods.  This 
is intended to allow for drop-in replacement of `ObjectRef` with 
`Variant<Type1, Type2, ...>` in places that previously used a common base class.
   
   To ensure that each variant can be uniquely retrieved, no type stored within 
the variant may inherit from any other type within the variant.  This condition 
is checked at compile-time, with a `static_assert` explaining the limitation.  
This condition is necessary to mimic the semantics of `std::variant`, whose 
active member depends on the compile-time type of an object.  Without this 
condition, the expression `Variant<PrimExpr, tir::Var> variant = PrimExpr(...)` 
could populate either of the variants depending on the run-time type of an 
object.  Because the `Variant` class is primarily intended for use when two 
types do not already inherit from each other, this limitation is not expected 
to limit its utility.
   
   There are several locations within the TVM codebase where this pattern may 
be useful, and which are currently worked around various strategies.  (This PR 
does not alter any existing implementations, instead introducing the `Variant` 
container that can be used in subsequent PRs, if desired.)
   
   * Workaround: Store a common base class.  For example, the type of 
`relax::TensorStructInfoNode::shape` is `Optional<Expr>`, with a comment 
stating that it should be only `NullOpt`, `ShapeExpr`, or `Var`.  However, 
these restrictions are not checked by the compiler, and a developer could 
erroneously provide a different type.  By expressing the type as as 
`Optional<Variant<Var,ShapeExpr>>`, these errors could be automatically caught.
   
   * Workaround: Use additional data structures.  For example, a `PrimFunc` 
parameter may be either a TIR primitive, which is lowered to a primitive type, 
or a TIR Buffer, which is lowered to a `DLTensor*` argument and appropriate 
unpacking code.  However, these two types are represented as an 
`Array<tir::Var>` and a `Map<tir::Var, tir::Buffer>`, which together represent 
a `Array<Variant<tir::Var, tir::Buffer>>`.  The separate data structures must 
be kept in sync whenever modified, such as when removing a parameter.
   
   * Workaround: Use `std::variant`.  For example, the 
`tvm::tir::IdentifyMemCpyImpl` utility function returns a `std::variant` with 
the result or an error message.  However, this is only suitable for use within 
a C++ implementation, and requires a wrapper in order to expose it to the FFI.


-- 
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: commits-unsubscr...@tvm.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to