What does #[NoDiscard] actually break in PHP 8.5?
PHP 8.5 introduced the #[\NoDiscard] attribute that warns when a return value is discarded. Several core functions now have this attribute, which means existing code can start generating E_DEPRECATED warnings where it did not before.
flock() now has #[\NoDiscard] on it, so calling flock($fh, LOCK_EX) without capturing the return value produces a warning. Makes sense since ignoring the flock() return means you might proceed without having actually acquired the lock. But in legacy code this pattern is everywhere.
Trying to understand the full scope: which other core functions got this attribute, and what is the right way to suppress it when you genuinely do not care about the return value?
The functions that got #[NoDiscard] in 8.5 are mostly ones where discarding the return value is almost always a bug: flock(), stream_set_blocking(), and DateTimeImmutable methods that return modified objects. The DateTimeImmutable one is particularly useful since the mutable vs immutable confusion causes real bugs.
DateTimeImmutable was the one that surprised me. Calling $dt->setTimezone($tz) without capturing the result is a logic bug that is very easy to write if you are used to DateTime. We had exactly this in one place that had been silently wrong for over a year. PHP 8.5 caught it on first run.
To suppress it intentionally when you genuinely do not need the return value: cast to void explicitly, like (void) flock($fh, LOCK_EX). This signals to the engine and to readers that the discard is intentional. Do not just suppress the warning with @ since that hides everything.
@irynaDev that DateTimeImmutable case is exactly what I was worried about. We have a lot of date manipulation code that was originally written with DateTime and later the type was switched to DateTimeImmutable without auditing all call sites. Running 8.5 would catch every one of those bugs. Might be the best argument for upgrading sooner.
```php blocks are runnable.