rectorphp/rector · error · ShouldNotHappenException

"%s" rule is deprecated, as it is a personal preference that

Error message

"%s" rule is deprecated, as it is a personal preference that makes array merges harder to read

What it means

ArraySpreadInsteadOfArrayMergeRector used to rewrite array_merge($a, $b) into [...$a, ...$b]. It is deprecated because the change is a personal preference that can make merges harder to read, and array_merge still differs from spread (string keys are overwritten rather than renumbered). refactor() now throws ShouldNotHappenException on every FuncCall node; the rule exists purely to fail configurations that still enable it.

Source

Thrown at rules/CodingStyle/Rector/FuncCall/ArraySpreadInsteadOfArrayMergeRector.php:61

        $anotherValues = [...$iter1, ...$iter2];
    }
}
CODE_SAMPLE
)]);
    }
    /**
     * @return array<class-string<Node>>
     */
    public function getNodeTypes(): array
    {
        return [FuncCall::class];
    }
    /**
     * @param FuncCall $node
     */
    public function refactor(Node $node): ?Node
    {
        throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, as it is a personal preference that makes array merges harder to read', self::class));
    }
}

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Remove ArraySpreadInsteadOfArrayMergeRector::class from rector.php and imported sets, then re-run dry-run
  2. Convert array_merge to spread manually only for hot paths with integer-keyed arrays
  3. Remember array_merge and spread are NOT equivalent for string keys — do not blindly swap
  4. If the style must be enforced, encode it in a review checklist or a scoped custom rule

Example fix

// before (rector.php)
->withRules([
    \Rector\CodingStyle\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
])
// code:
$all = array_merge($defaults, $overrides);

// after (rector.php)
// rule removed; manual conversion only where safe (integer keys):
$all = [...$defaults, ...$overrides];
// NOTE: with string keys, array_merge() and spread behave differently — keep array_merge()
Defensive patterns

Strategy: validation

Validate before calling

$deprecated = ['ArraySpreadInsteadOfArrayMergeRector'];
foreach (glob(__DIR__ . '/rector*.php') as $config) {
    $src = file_get_contents($config);
    foreach ($deprecated as $rule) {
        if (str_contains($src, $rule)) {
            fwrite(STDERR, "Remove deprecated rule {$rule} from {$config}\n");
            exit(1);
        }
    }
}

Prevention

When it happens

Trigger: Registering rules/CodingStyle/Rector/FuncCall/ArraySpreadInsteadOfArrayMergeRector.php and running rector over any file containing a function call. The throw comes from rules/CodingStyle/Rector/FuncCall/ArraySpreadInsteadOfArrayMergeRector.php:61 on the first FuncCall visited — effectively the first file.

Common situations: Configs that adopted the spread style for PHP 7.4+ performance still list this rule after upgrading rector/rector-prefixed. Since FuncCall matches every function call, the exception surfaces immediately and is often mistaken for a broken vendor directory.

Related errors


AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21). Data as JSON: /api/errors/08732e3e4e58947f. Report an issue: GitHub.