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

Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Any" with interface methods #1787

Closed
danielgordon10 opened this issue Apr 22, 2021 · 4 comments
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working

Comments

@danielgordon10
Copy link

danielgordon10 commented Apr 22, 2021

This is a somewhat niche problem, but I have come across it in practice twice already. It seems like the issue is caused by unimplemented methods in the base class which have type annotations being implemented in sub-classes. The resulting error looks like this:

Method "foo" overrides class "A" in an incompatible manner
  Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Any"

Adding the "Any" annotation doesn't seem to help either.

Sample code which causes the issue

from typing import Any, Callable

class A(object):
    def _foo_unimplemented(self, input: Any) -> None:
        raise NotImplementedError
    foo: Callable[..., Any] = _foo_unimplemented

class B(A):
    def foo(self, obj: Any):
        pass
    # Result: Method "foo" overrides class "A" in an incompatible manner.  Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Any"

# Real world examples
import tornado.web
class RunsHandler(tornado.web.RequestHandler):
    def initialize(self, con: Any):
        self._con = con
    # Result: Method "initialize" overrides class "RequestHandler" in an incompatible manner. Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Any"

import torch.nn
class Model(torch.nn.Module):
    def forward(self, data: Any):
        return data
    # Result: Method "forward" overrides class "Module" in an incompatible manner. Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Any"

class Model(torch.nn.Module):
    def forward(self, data):
        return data
    # Result: Method "forward" overrides class "Module" in an incompatible manner. Parameter 2 type mismatch: base parameter is type "Any", override parameter is type "Unknown"
@erictraut
Copy link
Collaborator

The current behavior is correct, or at least as intended. The intention behind the "reportIncompatibleMethodOverride" check is to detect cases where a base class is making assumptions that a subclass is violating. In your example above, A.foo is annotated as a callable type that accepts an arbitrary number of parameters (both positional and keyword) and returns any type. That implies that class A may call this function with any number of parameters. But B.foo is attempting to override it with a method that accepts only one positional parameter (obj) and no keyword parameters. If A calls it with any other combination of parameters, the program will crash at runtime. So this is exactly the sort of inconsistency that "reportIncompatibleMethodOverride" was designed to detect.

I think you have a few options here:

  1. Change the signature of foo in the base class so it reflects the fact that it accepts only one positional parameter.
  2. Change the signature of foo in the subclass so it accepts *args and **kwargs.
  3. If you don't want this check to be performed, you can disable it globally for your project. Or you can disable it for a specific file by using a comment (# pyright: reportIncompatibleMethodOverride=false).

@erictraut erictraut added the as designed Not a bug, working as intended label Apr 22, 2021
heejaechang pushed a commit to heejaechang/pyright that referenced this issue Nov 3, 2021
@okura25
Copy link

okura25 commented Apr 28, 2023

Hello. I also encountered this issue and tried to address it, but option 2 is not working. What should I do?

from typing import Any, Callable

class A(object):
    def _foo_unimplemented(self, input: Any) -> None:
        raise NotImplementedError

    foo: Callable[..., Any] = _foo_unimplemented


class B(A):
    def foo(self):
        pass
    # Result:
    # Method "foo" overrides class "A" in an incompatible manner
    # Positional parameter count mismatch; base method has 2, but override has 1
    # Parameter "args" is missing in override (reportIncompatibleMethodOverride)


class C(A):
    def foo(self, *args: Any):
        pass
    # Result:
    # Method "foo" overrides class "A" in an incompatible manner
    # Positional parameter count mismatch; base method has 2, but override has 2 (reportIncompatibleMethodOverride)


class D(A):
    def foo(self, *args: Any, **kwargs: Any):
        pass
    # Result:
    # Method "foo" overrides class "A" in an incompatible manner
    # Positional parameter count mismatch; base method has 2, but override has 3 (reportIncompatibleMethodOverride)

@erictraut erictraut reopened this Apr 28, 2023
@erictraut
Copy link
Collaborator

Yeah, I would expect option 2 to work in this case. It doesn't because of the self parameter that's present in the override but is not in the base. However, the ... should be treated specially in this case.

I've made this change, and it will be included in the next release.

@erictraut erictraut added bug Something isn't working addressed in next version Issue is fixed and will appear in next published version and removed as designed Not a bug, working as intended labels Apr 28, 2023
erictraut pushed a commit that referenced this issue Apr 28, 2023
…to exempt the case where the base class or override has a type that is defined by `Callable[..., X]`. The `...` means that it's compatible with any signature. Also fixed a false negative in this check where the base method contains a `**kwargs` parameter but the override does not. This addresses #1787.
@erictraut
Copy link
Collaborator

This is addressed in pyright 1.1.306, which I just published. It will also be included in a future release of pylance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addressed in next version Issue is fixed and will appear in next published version bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants