Skip to content

Detect more unused code

Choose a tag to compare
@muglug muglug released this 20 Jun 20:37
· 6117 commits to master since this release


New literal-string type

Inspired by the is_literal RFC we've added a new literal-string type.

The type will be most useful to annotate functions and methods that take SQL. In those methods you generally don't want any code that is not part of your app, e.g.


/** @param literal-string $sql */
function execute_sql(string $sql, array $params = []): void { }

$id = (string) ($_GET['id'] ?? '');

// passes type checks
    'SELECT * FROM `foo` WHERE `id` = :id',
    [':id' => $id]

// fails
    'SELECT * FROM `foo` WHERE `id` = "' .$id . '"'

Psalm’s taint analysis can also help detect this general class of issues, but a literal-string type allows the type-checker to provide guarantees much earlier in the process.

Read more in the documentation.

More specific taint analysis for unescaped quotes

htmlentities can be used to strip some harmful characters in strings, but not all of them (by default).

Psalm has a new issue TaintedTextWithQuotes to help detect strings that might not have HTML tags but can have harmful Javascript.

Detect unused return values

When running with the --find-unused-code flag, Psalm already detects a lot of unnecessary code, including unused public and private methods, unused properties and unused variables.

Now Psalm will also flag unused return values — where a function returns something, but nowhere that calls the given function actually uses the returned value.

See the documentation for UnusedReturnValue and PossiblyUnusedReturnValue for more information.

@var/@param mixup

@weirdan added a new issue that's emitted when using a @var docblock where @param is expected (#5845)

Plugins can declare custom scanners & analyzers

You've been able to set custom scanners and analyzers in your config, but now plugins can do this too — thanks @ohader (#5883)

Unused foreach values

@weirdan added a separate UnusedForeachVariable to unused variable detection to prevent Psalm incorrectly flagging unused foreach vars as fixable (#5932)


  • Taint analysis: @ohader added better tainting for var_dump and print_r output (#5827)
  • Taint analysis: @ohader ensured more errors are emitted after successful taint error found (#5832)
  • @weirdan ensured that errors are emitted for @internal calls when calling constructors (#5843)
  • @orklah fixed Psalter to add literal return type output (#5844)
  • @weirdan fixed Psalm signature for ReflectionClass::getConstants (#5847)
  • @orklah fixed an issue where Psalter was using the wrong PHP version (#5855)
  • @kesselb improved the signature of mb_convert_encoding (#5862)
  • @franmomu improved Mongodb signatures (#5864)
  • @klimick fixed some bugs with generic assertions (#5879, #5888)
  • fixed a bunch of issues around the use of assignment operators, which are now treated more like assignments
  • @weirdan restricted the types for spl_autoload functions (#5885)
  • @weirdan fixed method return types on DomNode classes (#5895)
  • @weirdan improved the signature for sscanf (#5901)
  • @weirdan prevented a crash when class constant references a missing class (#5902)
  • @christeredvartsen updated signatures for SessionHandlerInterface (#5904)
  • fixed inference of non-terminating switch statements (#5911)
  • @BafS fixed an uncaught TypeError with some problematic bit shifts (#5921)
  • Prevented a crash when dealing with non-UTF-8 strings (#5945)
  • @orklah allowed Psalter to fix RedundantCast (#5948)
  • @orklah prevented an infinite loop when a class constant referenced itself (#5951)
  • @danog fixed rdkafka signatures (#5950)