Skip to content

Conversation

@eellison
Copy link
Contributor

@eellison eellison commented Sep 24, 2019

Allowing invoking of a UDT if they have a __call__ method

Fix for #26725

@eellison eellison requested a review from apaszke as a code owner September 24, 2019 19:32
@pytorchbot pytorchbot added the oncall: jit Add this issue/PR to JIT oncall triage queue label Sep 24, 2019
@eellison eellison requested a review from driazati September 24, 2019 19:32
@eellison eellison changed the title [JIT] make class types callable [WIP][JIT] make class types callable Sep 24, 2019
@eellison eellison force-pushed the make_class_types_callable branch from bdd4314 to 66ab011 Compare September 25, 2019 19:44
@eellison eellison changed the title [WIP][JIT] make class types callable [JIT] make class types callable Sep 25, 2019
@eellison eellison requested a review from suo September 25, 2019 19:44
suo
suo previously requested changes Sep 25, 2019
auto inputs = getNamedValues(apply.inputs(), true);
auto attributes = emitAttributes(apply.attributes());

auto simple_value = std::dynamic_pointer_cast<SimpleValue>(sv);
Copy link
Member

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.

Copy link
Contributor Author

@eellison eellison Sep 25, 2019

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.

Copy link
Member

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.

Copy link
Contributor Author

@eellison eellison Sep 25, 2019

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.

@eellison eellison requested a review from suo September 25, 2019 22:49
}

if (auto class_type = getValue()->type()->cast<ClassType>()) {
auto self_nv = NamedValue(loc, "self", getValue());
Copy link
Member

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.

Copy link
Contributor Author

@eellison eellison Sep 26, 2019

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?

Copy link
Contributor

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.

Copy link
Contributor Author

@eellison eellison Sep 27, 2019

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 ?

Copy link
Contributor

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.

Copy link
Contributor Author

@eellison eellison Sep 30, 2019

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.

@eellison eellison requested a review from suo September 26, 2019 17:31
@eellison eellison added this to the 1.3 milestone Sep 26, 2019
@eellison eellison dismissed suo’s stale review September 27, 2019 15:34

no longer dynamic casting in that part of the code base

@eellison eellison requested a review from zdevito September 27, 2019 15:34
@eellison
Copy link
Contributor Author

@pytorchbot rebase this please

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a 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.

@facebook-github-bot
Copy link
Contributor

@eellison merged this pull request in 990f4ca.

eellison pushed a commit that referenced this pull request Oct 2, 2019
Summary:
Allowing invoking of a UDT if they have a `__call__` method

Fix for #26725
Pull Request resolved: #26743

Differential Revision: D17677795

Pulled By: eellison

fbshipit-source-id: 0ceb6088e22c4689e0735fdb9e07418a75603486
soumith pushed a commit that referenced this pull request Oct 4, 2019
Summary:
Allowing invoking of a UDT if they have a `__call__` method

Fix for #26725
Pull Request resolved: #26743

Differential Revision: D17677795

Pulled By: eellison

fbshipit-source-id: 0ceb6088e22c4689e0735fdb9e07418a75603486
soumith pushed a commit that referenced this pull request Oct 7, 2019
Summary:
Allowing invoking of a UDT if they have a `__call__` method

Fix for #26725
Pull Request resolved: #26743

Differential Revision: D17677795

Pulled By: eellison

fbshipit-source-id: 0ceb6088e22c4689e0735fdb9e07418a75603486
pdlive215 pushed a commit to pdlive215/pytorch that referenced this pull request Nov 27, 2019
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged oncall: jit Add this issue/PR to JIT oncall triage queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants