What's Changed
Features
- Rewrite dead-code detection on a code-use graph and infer purity across the call
graph. Unused-code detection now runs on a directed graph of references between code
elements (Psalm\Internal\Codebase\CodeUseGraph), in the same way as taint analysis:
a class, method, property or class constant is only considered used if it is reachable
from an entry point (the public API, top-level code, free functions, or code outside
the analysed project). Code referenced only by other unused code — including cycles of
otherwise unreferenced code — is now reported, and dead reads no longer keep
constructor-only-written properties alive.MissingPureAnnotation(and its--alter
fix) is inferred as a fixpoint over the call graph, handling call chains in any order,
mutual recursion, recursive closures and closures assigned to a variable.
--find-unused-psalm-suppressnow also reports redundant@psalm-suppresson
classes/interfaces/traits/enums and, under--taint-analysis, onTainted*issues.
All non-internal classes and interfaces are marked@api. @danog in #11939 - Add type variable support for class templates: class templates that cannot be inferred
at the construction site are tracked as type variables whose bounds are reconciled once
the surrounding function has been analysed, legalizing widening within a template's
declared bounds and introducing the newIncompatibleTypeParametersissue (level 1),
documented in https://psalm.dev/docs/annotating_code/type_variables
by @muglug in #11875
Fixes
- Fix
echo/print/exittaint sinks not matching their argument nodes (which broke
allTaintedHtmldetection through those constructs), fix taint tracking through
namespaced functions, and fix a crash on tainted closure/callable invocations, as part
of refactoring theDataFlowNodefactories
by @danog in #11887 - Fix multithreaded taint-analysis determinism, and report call-map sinks at the call
site by @danog in #11887 - Keep foreach key/value non-nullable after a breaking loop
by @muglug in #11874 - Fix
$thisfailing to parse inside generic type parameters
by @alies-dev in #11768 - Ignore inline
covariant/contravariantvariance modifiers in generic type
parameters instead of reportingUndefinedDocblockClass(backport)
by @alies-dev in #11836 - PHP 8.5 compatibility:
TLiteralFloatnow rendersNANvalues asfloat(NAN)in
type keys and IDs instead of crashing, plus assorted 8.5 fixes
by @danog in 9d6db9ec7 and ca151242c - Fix CI setup, static analysis, and dependency compatibility
by @muglug in #11934
Docs
- Document graph-based unused-code detection, purity inference and extended
--find-unused-psalm-suppresschecking indocs/running_psalm/configuration.md,
docs/annotating_code/supported_annotations.md,
docs/running_psalm/issues/MissingPureAnnotation.mdand
docs/running_psalm/issues/UnusedPsalmSuppress.md, and update the CLI help
by @danog in #11939 - Add
docs/annotating_code/type_variables.mdand theIncompatibleTypeParameters
issue page by @muglug in #11875
Internal changes
- Refactor the
DataFlowNodefactories: mandatory$storage, typed callable kinds,
and explicit locations by @danog in #11887 - Remove dead write-only static properties and simplify
ScopeAnalyzer
break/continue logic by @muglug in #11889 - Clean up redundant assignment-conditions and repeated
getArgs()calls
by @muglug in #11888 - Pin GitHub Actions to SHA for supply chain security
by @riccardosarro in #11863 - Test-fixture fixes: whitelist
Overridein the SuicidalAutoloader fixture and drop
the incorrectimpure-Closure prefix inTypeParseTest
by @alies-dev in #11835 and #11834
Other changes
- Allow
sebastian/diff9
by @liviuconcioiu in #11861
New Contributors
- @riccardosarro made their first contribution in #11863
Full Changelog: 7.0.0-beta19...7.0.0-beta20