Add generic return type for the PHP 8.5 clone() function#11884
Conversation
|
Heads up for reviewers: the failing Two open questions for maintainers are noted in the PR description: (1) whether the two-argument |
The clone() function only exists in PHP 8.5+. Defining its stub in CoreGenericFunctions.phpstub registered it unconditionally for all analysis target versions, so Psalm would silently accept clone($x, [...]) even when analyzing code targeting PHP < 8.5. Php85.phpstub is only loaded when analysis_php_version_id >= 8_05_00.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit e9d13ed. Configure here.
Summary
PHP 8.5 adds a function form of
clone,clone(object $object, array $withProperties = []), which PR #11604 registered inCallMap_85with a plainobjectreturn type. That loses the concrete type of the cloned object, soclone($user, [...])is inferred asobjectrather thanUser.This adds a templated stub to
stubs/Php85.phpstubso the function form returns the same type as its first argument:This mirrors what
CloneAnalyzeralready does for theclone $xoperator form (it preserves the operand's type).Tests
Adds a case to
tests/CloneTest.php(pinned tophp_version: 8.5) assertingclone($a, [...])is inferred as the argument's class.Notes
I split this out from the
array_first/array_last/array_any/array_allgenerics (separate PR) becausecloneis a reserved keyword and this needs your eyes.Routing —
CloneAnalyzerhandles theClone_AST node (theclone $xoperator). I'm assuming the two-argument function formclone($x, [...])is parsed as a regular call and resolves against the CallMap/stub (consistent with #11604 addingclonetoCallMap_85). If it is instead routed throughClone_/CloneAnalyzer, this stub won't apply and the fix belongs there or in a return-type provider instead.Placement — the stub lives in
stubs/Php85.phpstub, which is only registered whenanalysis_php_version_id >= 8_05_00. This gates the function to PHP 8.5+ so Psalm doesn't treatclone(...)as a valid call when analyzing code targeting earlier versions (an earlier revision placed it inCoreGenericFunctions.phpstub, which is loaded unconditionally — fixed per Cursor Bugbot's review).