Skip to content

Fix PHP 8.6 deprecations from DateTimeImmutable tentative return types - #767

Open
dhrupo wants to merge 1 commit into
thecodingmachine:masterfrom
dhrupo:php86-datetimeimmutable-return-types
Open

dhrupo wants to merge 1 commit into
thecodingmachine:masterfrom
dhrupo:php86-datetimeimmutable-return-types

Conversation

@dhrupo

@dhrupo dhrupo commented Oct 30, 2026

Copy link
Copy Markdown

PHP 8.6 gives several DateTimeImmutable methods a tentative static return type. Safe\DateTimeImmutable overrides them with self, so loading the class on 8.6 emits nine deprecation notices, for example:

Return type of Safe\DateTimeImmutable::modify($modify): Safe\DateTimeImmutable should either be compatible with DateTimeImmutable::modify(string $modifier): static, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice

This marks add(), sub(), modify(), setDate(), setISODate(), setTime(), setTimestamp(), setTimezone() and createFromInterface() with #[\ReturnTypeWillChange], as createFromMutable() and __set_state() already are.

The new test loads the class in a separate process and asserts no deprecation is raised. It fails on 8.6.0-dev without the change. The full suite passes on PHP 8.1 to 8.6.

PHP 8.6 gives DateTimeImmutable::add(), sub(), modify(), setDate(),
setISODate(), setTime(), setTimestamp(), setTimezone() and
createFromInterface() a tentative static return type. Safe's overrides
return self, so declaring the class emits nine deprecation notices.

Mark them #[\ReturnTypeWillChange], as createFromMutable() and
__set_state() already are.
@dhrupo

dhrupo commented Nov 1, 2026

Copy link
Copy Markdown
Author

The failing checks here are not caused by this branch: PHPStan fails the same way on a clean master.

Running the repo's own phpstan.neon on master at b713b22, with phpVersion set explicitly, gives:

phpVersion errors on clean master
8.1 lib/DateTime.php 43, 55, 58, 75 + lib/DateTimeImmutable.php 99 (5)
8.3 lib/DateTime.php 43, 55, 58, 75 (4)
8.6 lib/DateTime.php 43, 58, 75 + lib/DateTimeImmutable.php 246 (4)

This branch produces the same set, with the lib/DateTimeImmutable.php line shifted by the nine lines it adds. master shows green only because the Tests workflow last ran there on 24 October; phpstan.neon sets no phpVersion, so each matrix job analyses as its own version.

Since the three lib/DateTime.php errors appear at 8.1, 8.3 and 8.6 alike, no pull request can turn this workflow green until that file is addressed. I have opened a separate issue for it rather than widen this change.

What this branch does fix, measured on 8.6.0-dev (built 24 October) by loading the class directly, so Composer's autoloader cannot resolve to another checkout:

deprecations on load
Safe\DateTimeImmutable, master 18
Safe\DateTimeImmutable, this branch 0

Safe\DateTime emits none on 8.2, 8.3 or 8.6, so this is specific to the immutable class.

At phpVersion 8.1 it also removes the lib/DateTimeImmutable.php:99 PHPStan error (Safe\DateTimeImmutable::modify() not covariant with the tentative static(DateTimeImmutable)|false).

One note on createFromInterface(): PHPStan reports that one as method.childReturnType, which the attribute does not suppress, so it is still listed at 8.6. The attribute is required at runtime even so — removing just that one brings its deprecation back on 8.6. PHPStan's stubs and PHP disagree about whether that parent return type is tentative.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant