-
Notifications
You must be signed in to change notification settings - Fork 26.3k
[JIT] make class types callable #26743
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
Conversation
bdd4314 to
66ab011
Compare
torch/csrc/jit/script/compiler.cpp
Outdated
| auto inputs = getNamedValues(apply.inputs(), true); | ||
| auto attributes = emitAttributes(apply.attributes()); | ||
|
|
||
| auto simple_value = std::dynamic_pointer_cast<SimpleValue>(sv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should go in the call implementation in SimpleValue. In general, we should consider dynamic_casting an anti-pattern in this part of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't work, because you have to add the classtype value as the self argument. In the test example:
MyClass(1) inputs here are just 1. You need to check here if we're calling a classtype so that we can add the callee to the list of arguments, otherwise at the point of SimpleValue::call the callee will be lost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand—why can't you do that in SimpleValue::call()? You have access to self there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh got it to work. I tried the way you suggested previously but I forgot to emplace the self argument.
| } | ||
|
|
||
| if (auto class_type = getValue()->type()->cast<ClassType>()) { | ||
| auto self_nv = NamedValue(loc, "self", getValue()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are adding self to inputs here, only to slice it off in callClassMethod above. We seem to be piling pieces on top of each other here; it's not clear that callClassMethod should exist at all—could not be expressed as a composition of operations on sugared values? attr lookup (to get the __call__ MethodValue), then calling the method with the provided arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an attr lookup above would give the error message:
Tried to access nonexistent attribute
__call__. Did you forget to initialize it in __init__()?:
The error message with callClassMethod is:
Foo does not define a __call__ method
which is a better error message. separately, looking up an attr and trying to call it is not actually correct - if a class has an attribute __call__ that is callable but is not a method than you can not invoke the class as a callable.
Also - asking to inline a function that expresses a common pattern (it's invoked three times in this file) seems like a nit to me. Could we accept PRs when the only remaining comments are nits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code does seem like a bandaid. Attribute lookup is how we always lookup methods. If the error message is bad here it is also bad for standard method lookup. It's fine to want to improve that but it is not ok to just fix it in this instance and add more code to maintain. I do not think it is a good habit to think these kinds of things are nits. By adding more pathways here rather than using existing ones, it leaves the code in worse shape than where we started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message is bad because attr lookup in general does not have the additional context that we are looking for a method instead of another type of attribute (did you forget to initialize it in __init__()?. There isn't another pathway besides magic methods in which you know the attr is expected to be a method. In other cases our error messages have been overly general and not applied to the actual problem at hand and it's led to confused users (did you forget to add it to __constants__?).
This is specializing an error message when we know more information. That can't be a general anti-pattern - so in this case are the comments just saying that the additional specialization isn't worth the improvement in error message ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute lookup is how we always lookup methods. This means the error for missing methods is always this bad. This code fixes it for the case of only call __call__. I am asking that is is either fixed for all methods or not fixed at all. The middle ground is more code to maintain and is still not good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed callClassMethod. It fixed it for all magic methods not just __call__ (which is the only time you know you're looking up a method) but anyway I updated the PR to remove the extra path.
no longer dynamic casting in that part of the code base
|
@pytorchbot rebase this please |
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eellison is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
Summary: Allowing invoking of a UDT if they have a `__call__` method Fix for pytorch#26725 Pull Request resolved: pytorch#26743 Differential Revision: D17677795 Pulled By: eellison fbshipit-source-id: 0ceb6088e22c4689e0735fdb9e07418a75603486
Allowing invoking of a UDT if they have a
__call__methodFix for #26725