Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Object] Implemented .as<T> for ObjectRef param, returns Optional<T> #14522

Merged
merged 4 commits into from
Apr 11, 2023

Conversation

Lunderberg
Copy link
Contributor

Prior to this PR, the ObjectRef::as<T>() method could be used for any T that inherits from tvm::Object, and would return a const T* if the class could be cast to the specified type, or nullptr otherwise. However, if the caller needed a ObjectRef, they would then need to call GetRef<MyObjRef> to convert from a const T*.

This PR extends ObjectRef::as<T> to operate on a T that inherits from tvm::ObjectRef as well. In this case, the return type is Optional<T>, returning either an instance of the specified subclass, or NullOpt if the object was not an instance of the specified subclass. Example usage of this new conversion, along with how it relates to existing functionality, is shown below.

// Unconditionally convert, throwing an exception if the object isn't
// of the specified type.  In contexts where the type of the object is
// unknown, this shouldn't be used.
PrimExpr expr = Downcast<PrimExpr>(obj);

// Protect the Downcast from throwing an exception using IsInstance.
// This avoids the error, but performs the type-checking twice.  In
// addition, it requires the caller to specify both the ObjectRef
// subclass and the Object subclass, even though these usually have a
// 1:1 correspondence.
if (obj->IsInstance<PrimExprNode>()) {
  PrimExpr expr = Downcast<PrimExpr>(obj);
}

// Perform both type-checking and downcasting with the ObjectRef::as()
// method, then use GetRef to convert to an ObjectRef.  This avoids
// double-checking the type, but still requires the caller to
if (const PrimExprNode* ptr = obj.as<PrimExprNode>()) {
  PrimExpr expr = GetRef<PrimExpr>(ptr);
}

// New method introduced by this PR.  The type-checking is only
// performed once, and the Object subclass is inferred from the
// ObjectRef subclass.
if (Optional<PrimExpr> opt = obj.as<PrimExpr>()) {
  PrimExpr expr = opt.value();
}

This PR is implemented as two commits. The first commit implements the new functionality, but makes no further changes. The second commit looks for cases where object_ref.as<TNode>() was immediately followed by GetRef<T>(), replacing with either object_ref.as<T>() or with Downcast<T>(object_ref).

Prior to this commit, the `ObjectRef::as<T>()` method could be used
for any `T` that inherits from `tvm::Object`, and would return a
`const T*` if the class could be cast to the specified type, or
`nullptr` otherwise.  However, if the
caller needed a `ObjectRef`, they would then need to call
`GetRef<MyObjRef>` to convert from a `const T*`.

This commit extends `ObjectRef::as<T>` to operate on a `T` that
inherits from `tvm::ObjectRef` as well.  In this case, the return type
is `Optional<T>`, returning either an instance of the specified
subclass, or `NullOpt` if the object was not an instance of the
specified subclass.  Example usage of this new conversion, along with
how it relates to existing functionality, is shown below.

```c++
// Unconditionally convert, throwing an exception if the object isn't
// of the specified type.  In contexts where the type of the object is
// unknown, this shouldn't be used.
PrimExpr expr = Downcast<PrimExpr>(obj);

// Protect the Downcast from throwing an exception using IsInstance.
// This avoids the error, but performs the type-checking twice.  In
// addition, it requires the caller to specify both the ObjectRef
// subclass and the Object subclass, even though these usually have a
// 1:1 correspondence.
if (obj->IsInstance<PrimExprNode>()) {
  PrimExpr expr = Downcast<PrimExpr>(obj);
}

// Perform both type-checking and downcasting with the ObjectRef::as()
// method, then use GetRef to convert to an ObjectRef.  This avoids
// double-checking the type, but still requires the caller to
if (const PrimExprNode* ptr = obj.as<PrimExprNode>()) {
  PrimExpr expr = GetRef<PrimExpr>(ptr);
}

// New method introduced by this PR.  The type-checking is only
// performed once, and the Object subclass is inferred from the
// ObjectRef subclass.
if (Optional<PrimExpr> opt = obj.as<PrimExpr>()) {
  PrimExpr expr = opt.value();
}
```
@tvm-bot
Copy link
Collaborator

tvm-bot commented Apr 6, 2023

Thanks for contributing to TVM! Please refer to the contributing guidelines https://tvm.apache.org/docs/contribute/ for useful information and tips. Please request code reviews from Reviewers by @-ing them in a comment.

  • No users to tag found in teams: object See #10317 for details

Generated by tvm-bot

This commit looked for cases where `ObjectRef::as<ObjectSubclass>()`
was used to convert to a `const ObjectSubclass*` followed immediately
by a call to `GetRef<ObjectRefSubclass>()`, and replaced them with a
single call to `ObjectRef::as<ObjectRefSubclass>()`.
Copy link
Contributor

@kparzysz-quic kparzysz-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants