Skip to content

Conversation

@acoulton
Copy link
Contributor

ArrayToFirstClassCallableRector currently skips over all callables that reference non-public methods, even if the callable is defined in the same scope as the method (e.g. [$this, 'somePrivateMethod']).

There are no existing test fixtures that demonstrate this behaviour either as an expected refactor or as an expected skip (the examples are all using public methods, or references from outside the owning scope).

It looks like this was the behaviour before #5929 was merged into v1.1.1. That was a bugfix for rectorphp/rector#8659 which was specific to cases where a private method is referenced from outside the owning scope.

I'm not sure if it was intentional to also stop refactoring callables that are defined and used within the same class? As far as I can tell, those should always be safe to convert to first-class callables.

I've added a test fixture to prove that these nodes are not currently refactored, and will push a second commit with a fix.

If you're not convinced about changing the default behaviour, then I could instead make this a configurable option for the rule?

If a class contains array callbacks with a non-public method, they are
not converted into first-class callables. This is due to a fix for a bug
that was specific to skipping non-public methods referenced from
*outside* the owning class - there was no previous coverage for what
should happen when a callable is referenced within a valid scope.
If an array callable is explicitly referencing `$this`, then it should
always be safe to convert it to a first-class callable even if the
method is private / protected.

This was the original behaviour of the 8.1 fixers, but it changed in
v1.1.1 following a fix for cases where a private / protected method was
being referenced from outside the owning scope.
acoulton added a commit to Behat/Behat that referenced this pull request Dec 18, 2025
We still had a few uses of array callables within our internal code,
which I found when starting to look at adding parameter types to
internal methods.

Rector has a rule to fix these as part of the PHP 8.1 set that we are
running, but it had skipped over them because they were not public
methods, even though they are defined and used in their own scope.

I think this may actually be a Rector bug - see
rectorphp/rector-src#7760 for the patch which I
have temporarily used locally to convert these.

Refactoring them to first-class callables will help Rector (and possibly
phpstan) to make better decisions about parameter & return types in
future.
@acoulton acoulton requested a review from samsonasik December 18, 2025 08:18
@TomasVotruba TomasVotruba merged commit 112deba into rectorphp:main Dec 18, 2025
81 of 83 checks passed
@TomasVotruba
Copy link
Member

Thankl you 🥳

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants