rectorphp/rector · error · ShouldNotHappenException

"%s" is deprecated, as it removes intermediate variables tha

Error message

"%s" is deprecated, as it removes intermediate variables that carry naming and can be re-used later

What it means

Rector\Php85\Rector\StmtsAwareInterface\SequentialAssignmentsToPipeOperatorRector is deprecated: refactor() throws Rector\Exception\ShouldNotHappenException on the first StmtsAware node. The rule collapsed sequences like $a = f($b); $c = g($a); into a PHP 8.5 pipe chain, deleting the intermediate variables - but those variables carry naming intent and can be reused later, so removing them loses information and can break subsequent code. Like the other pipe rule it only loads for PHP 8.5 targets.

Source

Thrown at rules/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector.php:54

    |> function2(...)
    |> function3(...);
CODE_SAMPLE
)]);
    }
    public function getNodeTypes(): array
    {
        return NodeGroup::STMTS_AWARE;
    }
    public function provideMinPhpVersion(): int
    {
        return PhpVersionFeature::PIPE_OPERATOER;
    }
    /**
     * @param StmtsAware $node
     */
    public function refactor(Node $node): ?Node
    {
        throw new ShouldNotHappenException(sprintf('"%s" is deprecated, as it removes intermediate variables that carry naming and can be re-used later', self::class));
    }
}

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Remove SequentialAssignmentsToPipeOperatorRector from rector.php and keep the named intermediate variables.
  2. Only where a chain is clearly better, hand-write the pipe chain and verify no later statement referenced the removed variables.
  3. Do not carry the rule forward in shared/team configs; it will keep throwing on every run.

Example fix

// before (rector.php)
->withRules([SequentialAssignmentsToPipeOperatorRector::class])

// after (rector.php) - removed; keep named intermediates

// optional manual rewrite (PHP 8.5), only if $values/$filtered are unused later:
$values = getValues();            // return getValues() |> array_filter(...);
return array_sum(array_filter($values));
Defensive patterns

Strategy: validation

Validate before calling

use Rector\Php85\Rector\StmtsAwareInterface\SequentialAssignmentsToPipeOperatorRector;

$rules = [/* your list */ SequentialAssignmentsToPipeOperatorRector::class];
if (in_array(SequentialAssignmentsToPipeOperatorRector::class, $rules, true)) {
    throw new InvalidArgumentException('Rule deprecated; keep named intermediate variables');
}

Try / catch

try {
    exit($rectorApplication->run());
} catch (\Rector\Exception\ShouldNotHappenException $e) {
    if (str_contains($e->getMessage(), 'SequentialAssignmentsToPipeOperator')) {
        fwrite(STDERR, 'Remove the rule; intermediates carry naming and may be reused later.' . PHP_EOL);
        exit(1);
    }
    throw $e;
}

Prevention

When it happens

Trigger: The rule remains in a PHP 8.5 config and rector visits any statement-aware node (function body, method body, if branch, etc.); refactor() throws on the first match.

Common situations: Bulk-enabling Php85 rules during a 'modernize everything' pass; keeping the rule from an early pipe-operator experiment; CI breaking after rector removed the implementation.

Related errors


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