- Notifications
You must be signed in to change notification settings - Fork748
Operator overloads support#1324
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
christabella commentedDec 17, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
src/runtime/typemanager.cs Outdated
@@ -280,6 +280,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) | |||
{ | |||
throw new PythonException(); | |||
} | |||
OperatorMethod.FixupSlots(type, clrType); |
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.
Please address the comment that was made on this file in PR#907
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 have moved it up before pytype_ready
e0ebf2c
tob2053a7
Compare
lostmsu left a comment• edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
Overall looks good as a starting point. We need to keep in mind, that his does not give us full operator support.
- In C# and .NET only one argument of a binary operator must match the type, that defines it, and it does not have to be the first argument. This needs to be fixed in this PR: when adding operator methods only the methods where the left argument is of the parent type must be considered (and maybe also inherited ones). I think without this attempts to call the following overloaded operator on two instances of
OperableObject
would fail from Python:
classOperableObject{ ...OperableObjectoperator+(intleft,OperableObjectright)=> ...; ...OperableObject operator+(OperableObjectleft,OperableObjectright)=> ...;}
Binary operators, that have the first argument of different type need to be handled correctly. I think this should be done in a separate PR, because I expect the amount of work to be comparable or even greater: loading a new type might add overloads to existing type's
__add__
for example.A few operators are not covered here. The full list in C# is:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading . Notably missing comparison, bitwise, and obscure stuff like conversion to
true
/false
. I suggest we add them in a separate PR.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
c0b5569
to659ad56
CompareThank you for the review. Handling operators with asymmetrical types is a really good point. I have added the "forward" case where the arguments are OperableObject and int; I will add the "reverse" case where the arguments are int and OperableObject. |
@christabella I think the reverse case can be done in a separate PR. Until it is in, do you want me to review this one? |
@lostmsu Yes please, would appreciate your review once again. |
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 original PR#907 reduced some iterations, redundant checking, and heap allocation in order to improve the performance for the binding behavior, also it included the new style params matching, so it was quite different from the master branch.
If you don't need those enhance you don't need to port them all.
Uh oh!
There was an error while loading.Please reload this page.
2dd951d
to90cd7d3
CompareUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
90cd7d3
to3438982
CompareThere 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.
@christabella please, revert rename topynargs
too.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Also move fixupslots before pytype_ready.Also apply access violation fix in classderived.
@christabella this looks good to me. But considering the upcoming forward operator support and the |
@lostmsu sure I can do that, if you think it makes sense having seen the upcomingchristabella#1 |
lostmsu commentedDec 29, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@christabella actually, I suggested to create an You could probably also move some/all of But! It is not a requirement, you can also just leave code as-is. |
@lostmsu thanks for clarifying, I understand now. So that would be quite a refactor, for now I would try to keep this PR as-is. |
2fe1de7
toa376838
CompareUh oh!
There was an error while loading.Please reload this page.
src/runtime/classmanager.cs Outdated
// Only methods where the left operand is the declaring type. | ||
ci.members[pyName] = new MethodObject(type, name, forwardMethods); | ||
// Only methods where only the right operand is the declaring type. | ||
ci.members[pyNameReverse] = new MethodObject(type, name, reverseMethods); |
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.
What if there are no reverseMethods?
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.
Currently it will just create a method that's never used; I can fix that by adding a hasReverse field in the SlotDefinition struct.
christabellaDec 30, 2020 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
So if C# reverse operator isn't defined, so the Python reverse name will have an empty method list in MethodObject
So if a user callsb.__radd__(a)
by writinga + b
where there is no forward +() defined ona
so Python resorts to__radd__
, AND no reverse +() defined onb
, what happens? Wouldn't hurt to add a check for an empty reverseMethods before doingci.members[pyNameReverse] = new MethodObject(type, name, reverseMethods);
Another unrelated issue is that of doing unnecessary work, if the Python slot doesn't support reverse e.g. unary operators (__rtruediv__
exists even though python docs don't list them)
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.
It is also possible to have no "forward" methods.
If no reverse methods are defined, the corresponding slot should not be set. Same for forward.
Python slot doesn't support reverse e.g.
__truediv__
Not sure what you mean. There's__rtruediv__
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's true, I've just put a check then to not set the slot method if the method list is empty
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
cls = {name} | ||
a = cls(2) | ||
b = cls(10) | ||
c = a + b |
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.
At this point, both of these calls will succeed (and do the same thing):
a.op_Addition(b)a.op_Addition(a,b)
Is that desirable behavior?
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.
So the first statement would have previously failed and now succeeds. I guess this is a question for@lostmsu if we want to let something that's wrongly written, not fail
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.
a.op_Addition(a, b)
must be failing for operators, defined in C#.
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 code I wrote is Python code. Ifa.op_Addition(a,b)
now fails in Python.NET, then it will break existing code using Python.NET.
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.
Breaking should not be a big deal, since we are making major version bump with (hopefully) a good overhaul.
But I don't thinka.op_Addition(a, b)
should be working now.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
This partially reverts commit8cce61d.Due to breaking change
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
What does this implement/fix? Explain your changes.
Adapts@amos402's PR#907 for the latest Pythonnet version. I can also modify Amos's PR directly if that is more convenient for@amos402@lostmsu who have already made comments on it.
pynargs
andclrnargs
for readability and consistency with the rest of methodbinder.<<
and>>
) a separate test because they are quite different from the rest of the operators (+/-/&
etc.)---the C# language specification is such that that shift operators always need an int for the second arg:https://stackoverflow.com/questions/7586887/c-sharp-shift-operator-overload. Instead of doingc = a >> b
, we have to doc = a >> b.Num
or get an ArgumentException.__radd__
).Although Amos's PR had some params array tests, it looks like params array handling is currently being looked into by@filmor (#1304 and#1311), so I removed those for now, since they are not related to operator overloading.
Does this close any currently open issues?
Fixes#906.
Suggestions/future work
Checklist
Check all those that are applicable and complete.
AUTHORS
CHANGELOG