Skip to content

NarrowObjectReturnTypeRector replaces interface with implementing concrete class #9525

Closed
rectorphp/rector-src
#7700

Description

@WyriHaximus

Bug Report

Subject Details
Rector version e.g. v2.2.10 (invoke vendor/bin/rector --version)

Minimal PHP Code Causing Issue

https://getrector.com/demo/c43e917d-7f01-44c0-b43f-426f51ec938c

Expected Behaviour

No changes in the return type of Vhost\Healthz::handle. My expectation here was that Rector would respect the return type and anyone call that method should care about how I get to my return value, only that it implements that interface.

P.S. Not sure how much of this relates to #9489

Activity

  1. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    This is expected, the purpose is clear to get exact type when possible. You can skip the rule if needed

    https://getrector.com/documentation/ignoring-rules-or-paths

  2. WyriHaximus commented on Dec 1, 2025

    @WyriHaximus
    Author

    This is expected, the purpose is clear to get exact type when possible.

    This honestly wasn't expected, for the example on https://getrector.com/rule-detail/narrow-object-return-type-rector I get it, but a class implementing the interface you have as return type, no.

    You can skip the rule if needed
    https://getrector.com/documentation/ignoring-rules-or-paths

    Yeah I'm aware of that and will do that assuming this behavior won't be fixed, would have been nice if that could be done like PHPStan does with:

    /** @rectorphp-ignore NarrowObjectReturnTypeRector */
  3. TomasVotruba commented on Dec 1, 2025

    @TomasVotruba
    Member

    I agree with @WyriHaximus . I think we'll have to skip such cases, as it's not first time this was reported.
    It makes sense for implemented method, where it narrows the type. Here it would only override existing declared type.

  4. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    @TomasVotruba how about make it configurable? eg: allow_interface_to_exact_type, default to true?

  5. WyriHaximus commented on Dec 1, 2025

    @WyriHaximus
    Author

    @samsonasik Or make it a list of configurable interfaces?

  6. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    That also can be an option 👍

  7. TomasVotruba commented on Dec 1, 2025

    @TomasVotruba
    Member

    @TomasVotruba how about make it configurable? eg: allow_interface_to_exact_type, default to true?

    I'd prefer to exclude the case above, as its out of scope of this rule. There must be some parent method (interface or class) we override, so the narrow type in the rule name happens.

  8. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    I think interface with Psr\\ prefix can be skipped then

  9. TomasVotruba commented on Dec 1, 2025

    @TomasVotruba
    Member

    @samsonasik No parent class/interface → skip 👍

  10. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    no parent class can be JsonResponse -> Response -> ResponseInterface, while user may return:

    public function indexAction(): Response
    {
        return new JsonResponse();
    }

    which Response can be JsonResponse instead, that both Response and JsonResponse are instantiable.

  11. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    I check the fixtures and the origin PR about this, there are valid arguments which interface/abstract should be allowed, I think configurable should be the way, it can be true or false, but make it configurable is better imo.

    I will create a PR for it so it can be usefull, while allow user to configure it.

  12. samsonasik commented on Dec 1, 2025

    @samsonasik
    Member

    I created PR to make it configurable, imo, based on the long discussion we had in the original PR, this still valid, but make it configurable so user can choose the design they want:

  13. TomasVotruba commented on Dec 2, 2025

    @TomasVotruba
    Member
  14. WyriHaximus commented on Dec 2, 2025

    @WyriHaximus
    Author

    Fixed in released in https://github.com/rectorphp/rector/releases/tag/2.2.11

    Not that I was doubting, but can confirm this resolves the issue for me <3! Thank you all

  15. TomasVotruba commented on Dec 2, 2025

    @TomasVotruba
    Member

    Thank you @WyriHaximus 👍

  16. github-actions commented on May 3, 2026

    @github-actions
    Contributor

    This issue has been automatically locked because it has been closed for 150 days. Please open a new issue if you have a similar problem.

  17. locked as resolved and limited conversation to collaborators on May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions