-
Notifications
You must be signed in to change notification settings - Fork 983
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
Fix call signature on Gate to show that it takes Qids. #5235
Conversation
def __call__(self, *args, **kwargs): | ||
return self.on(*args, **kwargs) | ||
def __call__(self, *qubits: Qid, **kwargs): | ||
return self.on(*qubits) |
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 also need to pass the **kwargs
to self.on()
call, so that cirq.CNOT(control=a, target=b)
works ?
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 cirq.Gate
class defines the on
method as:
def on(self, *qubits: Qid) -> 'Operation':
...
whereas it's derived class, CXPowGate
, overrides the on
method as
def on(self, *args: 'cirq.Qid', **kwargs: 'cirq.Qid') -> raw_types.Operation:
...
Technically, this does satisfy the liskov substitution principle because the derived class is implementing a more generic method (that accepts both *args and **kwargs) compared to the base class (that can accept only *args).
I think your current solution, to not specify type of **kwargs
in __call__
and silently forwarding it to self.on()
, should work.
One other way could be to enforce that the cirq.Gate
's __call__
method will only accept *qubits
and whenever a derived class, like CXPowGate, overrides the on
method to be more generic, it should also override the __call__
method? But that would be a huge breaking change for all existing implementations, like CXPowGate
, and something we probably don't want to do at this point.
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.
yes sorry thought I had fixed this. This is what happens when check/all doesn't run tests in parallel so I just push it out without running the tests (I can haz review for #5006 ?)
cirq-core/cirq/ops/raw_types.py
Outdated
@@ -211,11 +211,13 @@ def validate_args(self, qubits: Sequence['cirq.Qid']) -> None: | |||
""" | |||
_validate_qid_shape(self, qubits) | |||
|
|||
def on(self, *qubits: Qid) -> 'Operation': | |||
def on(self, *qubits: Qid, **kwargs) -> 'Operation': |
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 is a breaking change because all user defined classes which override the on
method as def on(self, *qubits: Qid)
will now not satisfy LSP and would need to be updated?
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.
yeah agree this is less than happy, let me see if I can work around the other issue (we currently call on in call with the wrong signature and get away with it)
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.
Yeah, I think it wasn't an issue earlier because mypy was not type-checking the method at all, due to no type annotations. But now that's not the case and hence it raises an error.
We can also decide to make __call__
a more restrictive type on the base class, so if user overrides on
, they must also override __call__
-- but that would also be a breaking change.
Maybe @maffoo knows some mypy magic to get around the situation without having to deal with breaking changes.
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.
Maybe @maffoo knows some mypy magic to get around the situation without having to deal with breaking changes.
I got nothin', sorry :-)
@tanujkhattar PTAL I think this is the minimal change. It leaves the signatures the same, and to get around the CXPow gate it adds an explicit override for the |
So, what we have now is also a breaking change because every user defined class which was dependant on |
Hm, not sure I agree about that. This doesn't break any public interface, and if someone chose to follow the pattern of CXPowGate, they would be doing so in a manner that isn't really explicitly supported by any documented interface on Cirq's end. |
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.
Okay, I don't have very strong opinions here.
cc @MichaelBroughton and @95-martin-orion Do you have strong opinions on silently changing the behavior of a public interface and whether this should be a breaking change or not? We can merge if other maintainers don't have concerns.
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.
LGTM, all interfaces remain the same (modulo better type annotation) and internal refactors have the same end behavior.
I'm not a huge fan of this change solely in the name of getting better type hints (which has no functional impact by itself). There's also no super clear guidance on type hinting for |
I'm not sure I follow. Why would we ignore the type hints? |
So that we could fix the API docs issue without having to introduce any code changes until we can come up with a fix everyone was on board with. Maybe I'm missing something here, is this a docs motivated PR or do we want the code fix itself in this PR too ? |
The primary goal is to make sure all the gate constants have a reasonable doc string which shows they can be called on qubits. The type gets dropped by our beloved tensorflow doc overlords :) This doesn't end up changing any interface and really just changes where passing in kwargs fails for Really there was a bug as they should have been consistent with each other but fixing that is a breaking change. |
@MichaelBroughton let me know if you are OK with this, if not, also great and I will close this :) |
This makes the API documentation for our gate constants better. Not sure why it trips the type notation. ![image](https://user-images.githubusercontent.com/87974/162509043-87824a51-0a46-4346-a9ec-779202d56a26.png) Fixes quantumlib#5232
This makes the API documentation for our gate constants better. Not sure why it trips the type notation.
Fixes #5232