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

stubtest: False-positive errors for type[T] attributes with non-type metaclasses #13316

Open
AlexWaygood opened this issue Aug 3, 2022 · 2 comments · May be fixed by #13367
Open

stubtest: False-positive errors for type[T] attributes with non-type metaclasses #13316

AlexWaygood opened this issue Aug 3, 2022 · 2 comments · May be fixed by #13367
Labels
bug mypy got something wrong topic-stubtest

Comments

@AlexWaygood
Copy link
Member

Bug Report

Given a stub like so:

from abc import ABCMeta
class Y(metaclass=ABCMeta): ...
class Z:
    foo: type[Y]

And a runtime like so:

from abc import ABCMeta
class Y(metaclass=ABCMeta): ...
class Z:
    foo = Y

Stubtest will issue the following complaint:

error: Z.foo variable differs from runtime type abc.ABCMeta

This error can be reproduced with any custom metaclass; it's not just ABCMeta that triggers the bug:

# STUB
class Meta(type): ...
class Y(metaclass=Meta): ...
class Z:
    foo: type[Y]

# RUNTIME:
class Meta(type): ...
class Y(metaclass=Meta): ...
class Z:
    foo = Y

To Reproduce

  1. Check out a local clone of mypy
  2. Activate a virtual environment with an editable install of mypy
  3. Apply this diff:
diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py
index 2adbfaac2..60ddebc7f 100644
--- a/mypy/test/teststubtest.py
+++ b/mypy/test/teststubtest.py
@@ -208,6 +208,21 @@ class StubtestUnit(unittest.TestCase):
             """,
             error="X.mistyped_var",
         )
+        yield Case(
+            stub="""
+            class Meta(type): ...
+            class Y(metaclass=Meta): ...
+            class Z:
+                foo: type[Y]
+            """,
+            runtime="""
+            class Meta(type): ...
+            class Y(metaclass=Meta): ...
+            class Z:
+                foo = Y
+            """,
+            error=None
+        )
  1. Run pytest ./mypy/test/teststubtest.py

Expected Behavior

No error should be emitted.

Actual Behavior

An error was emitted.

Cc. @hauntsaninja

@AlexWaygood
Copy link
Member Author

The issue seems to be that the call to is_subtype_helper here returns False, whereas for a class without a metaclass, it returns True:

and not is_subtype_helper(runtime_type, stub.type)

@AlexWaygood AlexWaygood changed the title stubtest: False-positive errors for type[T] attributes with nonstandard metaclasses stubtest: False-positive errors for type[T] attributes with non-type metaclasses Aug 3, 2022
@hauntsaninja
Copy link
Collaborator

So the question is_subtype_helper gets posed is whether Meta is a subtype of type[Y]. This fails for the same reason that mypy will complain about x: type[Y] = Meta. The fix is probably some change in get_mypy_type_of_runtime_value — we currently always make Instances, but maybe we should have some complicated logic that comes up with TypeType for metaclasses? Might be a little tricky to get heuristics right, but subclass of type is hopefully good enough

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-stubtest
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants