Skip to content

fix: skip missing-super-call for abstract or protocol constructor overrides - #5474

Open
Aayushyaash wants to merge 2 commits into
meta:mainfrom
Aayushyaash:fix-missing-super-call-abstract-child
Open

Aayushyaash wants to merge 2 commits into
meta:mainfrom
Aayushyaash:fix-missing-super-call-abstract-child

Conversation

@Aayushyaash

@Aayushyaash Aayushyaash commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

In an executable .py file, when an abstract class or sub-protocol overrides a constructor method (__init__ or __new__) to declare or refine a signature with a placeholder body (..., pass, or raise NotImplementedError), Pyrefly reported a false-positive missing-super-call error.

While #5180 skipped .pyi stubs and if TYPE_CHECKING: blocks, overriding methods in runtime .py files were still required to call super(), even when the overriding method itself was an abstract or protocol declaration without a runtime implementation.

This PR updates check_missing_super_call_for_field() to skip the check for __init__ and __new__ when the overriding method is abstract or belongs to a Protocol and its body kind is BodyKind::Ellipsis, BodyKind::Trivial, or BodyKind::RaiseNotImplementedError.

Note on __init_subclass__: Unlike instance constructors, __init_subclass__ executes during class creation along the MRO (PEP 487). Omitting super().__init_subclass__() can prevent downstream subclass initialization hooks from running. Therefore, it is intentionally excluded from this bypass and retains the missing-super-call diagnostic.

Fixes #5431

  • I am a human, and I fully understand the code I am submitting.

Test Plan

Updated and added regression tests in pyrefly/lib/test/class_overrides.rs covering:

  • An abstract child class overriding __init__ with ....
  • An abstract child class overriding __init__ with pass.
  • An abstract child class overriding __init__ with raise NotImplementedError.
  • A sub-protocol overriding a parent protocol's __init__ with ..., where the parent protocol method has a concrete implementation.
  • Preserving the missing-super-call diagnostic when __init_subclass__ is overridden with a placeholder body in a Protocol hierarchy.

Validation:

cargo test -p pyrefly --lib test_missing_super_call
cargo test -p pyrefly --lib test::class_overrides::
python3 test.py --lint --no-test --no-conformance --no-jsonschema --no-extension
@meta-codesync

meta-codesync Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D128855918. (Because this pull request was imported automatically, there will not be any future comments.)

@github-actions

This comment has been minimized.

@stroxler stroxler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! AI review caught an edge case plus a test it thinks could be strengthened. I think we should look at these before we merge:

Preserve the warning for __init_subclass__

[class_field.rs:4227–4238](https://github.com/meta/pyrefly/blob/962300abed15f7a5ad8290fd057bd5567fa4d8dc/pyrefly/lib/alt/class/class_field.rs#L4227-L4238)

Unlike constructors, __init_subclass__ executes automatically when subclasses are defined—even for abstract classes and protocols. A placeholder override can therefore break a concrete parent’s initialization chain:

registry: list[type] = []

class Registered(Protocol):
    def __init_subclass__(cls) -> None:
        super().__init_subclass__()
        registry.append(cls)

class SubProto(Registered, Protocol):
    def __init_subclass__(cls) -> None:
        ...  # Keep missing-super-call here.

class Impl(SubProto):
    pass

CPython registers SubProto, but not Impl. The base revision reports the useful warning on SubProto.__init_subclass__; this PR suppresses it.

Suggested fix: add field_name != &dunder::INIT_SUBCLASS to the new guard and cover this example with an expected diagnostic.

Strengthen the protocol regression test

[class_overrides.rs:2478–2484](https://github.com/meta/pyrefly/blob/962300abed15f7a5ad8290fd057bd5567fa4d8dc/pyrefly/lib/test/class_overrides.rs#L2478-L2484)

This case already passes without the PR because the parent’s pass body triggers existing parent-side suppression. Give the parent a real implementation so the test exercises the new child-side rule.

@Aayushyaash
Aayushyaash force-pushed the fix-missing-super-call-abstract-child branch from 962300a to 5840c38 Compare November 1, 2026 19:33
@github-actions github-actions Bot added size/s and removed size/s labels Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@Aayushyaash Aayushyaash changed the title fix: skip missing-super-call for abstract or protocol method overrides Nov 1, 2026
@Aayushyaash

Copy link
Copy Markdown
Contributor Author

Thanks for the review and pointing out the __init_subclass__ edge case! I've updated the implementation to handle it separately and added a regression test to ensure the existing diagnostic behavior is preserved.

I've also updated the PR title, description and rebased cleanly onto the latest main.

Following changes were made:

  1. Preserved missing-super-call for __init_subclass__:

    • Added field_name != &dunder::INIT_SUBCLASS to the guard in class_field.rs.
    • Added a regression test using Registered, SubProtoInitSubclass, and Impl to verify that the diagnostic is still reported for placeholder overrides.
  2. Strengthened the protocol regression test:

    • Updated ParentProto.__init__ in class_overrides.rs to include a concrete implementation (self.x = x).
    • This ensures super_method_needs_impl_reason returns None for the parent, specifically exercising the new child-side suppression logic.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants