Skip to content

Re-add the @pure annotations#603

Merged
ramsey merged 5 commits into4.xfrom
fix-pure-annotations
Jun 25, 2025
Merged

Re-add the @pure annotations#603
ramsey merged 5 commits into4.xfrom
fix-pure-annotations

Conversation

@ramsey
Copy link
Copy Markdown
Owner

@ramsey ramsey commented Jun 22, 2025

Description

Add @pure annotations where the @psalm-pure annotations used to be.

Motivation and context

These were removed in 691c2c8 but should remain in the code base.

For more information, see discussion at 691c2c8#r160296998

How has this been tested?

Static analysis is now failing on each @pure method. I will need some help resolving the failures.

Thanks to @fillerwriter (see #605), static analysis is now passing!

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

PR checklist

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING.md document.
  • I have added tests to cover my changes.

@ramsey
Copy link
Copy Markdown
Owner Author

ramsey commented Jun 22, 2025

@Ocramius I've re-added the @pure annotations, so static analysis is now failing (as expected, I guess). I could use some direction on what's needed to fix the failures. Thanks!

@ramsey ramsey force-pushed the fix-pure-annotations branch from 0bc8963 to d638959 Compare June 22, 2025 23:14
@fillerwriter
Copy link
Copy Markdown
Contributor

👋 Hello! I've spent some time on this branch, and here's my current thinking, along with an approach.

I'm planning on working through the error list this morning, but wanted to drop this into the PR thread to make sure that folks were on board with this approach before getting too far into it.

ramsey pushed a commit that referenced this pull request Jun 25, 2025
Coming from #603, this is an attempt
to fix the errors raised by the current phpstan settings.

I went through each of the errors raised by phpstan with the following
approach.

- If a method is part of an `@immutable` class, we can consider it pure,
  assuming it only affects internal variables.
- If a potentially pure method is calling a class's method that is only
  swapped during testing (and not during normal usage), then we can
  consider the calling method pure.
- If a class is marked deprecated, don't bother with attempting to mark
  it pure or immutable.
@codecov
Copy link
Copy Markdown

codecov bot commented Jun 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.11%. Comparing base (dbc8104) to head (198a34a).

✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##                4.x     #603      +/-   ##
============================================
+ Coverage     95.06%   95.11%   +0.04%     
  Complexity      574      574              
============================================
  Files            70       70              
  Lines          1622     1637      +15     
============================================
+ Hits           1542     1557      +15     
  Misses           80       80              
Files with missing lines Coverage Δ
src/BinaryUtils.php 100.00% <ø> (ø)
src/Builder/DegradedUuidBuilder.php 100.00% <ø> (ø)
src/Builder/FallbackBuilder.php 100.00% <ø> (ø)
src/Codec/GuidStringCodec.php 100.00% <ø> (ø)
src/Codec/OrderedTimeCodec.php 100.00% <ø> (ø)
src/Codec/StringCodec.php 100.00% <ø> (ø)
src/Codec/TimestampFirstCombCodec.php 100.00% <ø> (ø)
src/Converter/Number/BigNumberConverter.php 100.00% <ø> (ø)
src/Converter/Number/GenericNumberConverter.php 100.00% <ø> (ø)
src/Converter/Time/GenericTimeConverter.php 100.00% <100.00%> (ø)
... and 22 more

ramsey and others added 4 commits June 24, 2025 20:33
These were removed in 691c2c8 but
should remain in the code base.
Coming from #603, this is an attempt
to fix the errors raised by the current phpstan settings.

I went through each of the errors raised by phpstan with the following
approach.

- If a method is part of an `@immutable` class, we can consider it pure,
  assuming it only affects internal variables.
- If a potentially pure method is calling a class's method that is only
  swapped during testing (and not during normal usage), then we can
  consider the calling method pure.
- If a class is marked deprecated, don't bother with attempting to mark
  it pure or immutable.
@ramsey ramsey force-pushed the fix-pure-annotations branch from 147b960 to 198a34a Compare June 25, 2025 01:35
@ramsey
Copy link
Copy Markdown
Owner Author

ramsey commented Jun 25, 2025

Thanks so much for your help, @fillerwriter!

@Ocramius, I'd love for you to take a final glance at this before I merge it into the 4.x branch. We're now adding @pure in some places where it wasn't before, and I want to make sure this doesn't also create a BC break.

If it's considered new, backward-compatible functionality, then all is well, and I'll tag a 4.x.0 release. Otherwise, I want to remove the annotations that cause BC breaks for 4.x, while keeping everything for the 5.x branch.

@ramsey
Copy link
Copy Markdown
Owner Author

ramsey commented Jun 25, 2025

@fillerwriter, I addressed your concerns about the PHPStan errors in the tests here: 198a34a

I'm still not sure why it only just now started complaining about that.

@fillerwriter
Copy link
Copy Markdown
Contributor

Nice! Re: PHPStan errors in tests, that's a nice trick! I didn't know you could filter errors based on the folder.

@ramsey
Copy link
Copy Markdown
Owner Author

ramsey commented Jun 25, 2025

I didn't know you could filter errors based on the folder.

I didn't, either, but I suspected you could, so I figured that out tonight. 🙂

@Ocramius
Copy link
Copy Markdown
Contributor

@ramsey fwiw, @fillerwriter's analysis is correct, and the suppressions correspond to my initial design too (which is also what highlighted the entire factory problematic under the hood)

Copy link
Copy Markdown
Contributor

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my PoV, this patch reflects the initial design when @pure was introduce.

The only thing that is a bit annoying is the fact that we need to suppress inline so much, but on the other end, it was kinda expected.

LGTM

{
public function encode(UuidInterface $uuid): string
{
/** @phpstan-ignore possiblyImpure.methodCall */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep inside these implementations, I'd suggest suppressing the entire category of errors at class level, where needed

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried adding @phpstan-ignore at the method level, and it wouldn't work. PHPStan was telling me there wasn't a possiblyImpure.methodCall error on the next line. The only way I could find to squelch the errors is to inline them like this or add them to the config file, but I'd rather leave them in the code.

Comment on lines 91 to 94
/** @phpstan-ignore possiblyImpure.methodCall */
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
/** @phpstan-ignore possiblyImpure.methodCall */
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting here: getFields() gets called twice, which is a small thing to optimize away, and reduces us to a single suppression

@ramsey ramsey merged commit 1fffdc3 into 4.x Jun 25, 2025
29 checks passed
@ramsey ramsey deleted the fix-pure-annotations branch June 25, 2025 13:24
ramsey pushed a commit that referenced this pull request Jun 25, 2025
Coming from #603, this is an attempt
to fix the errors raised by the current phpstan settings.

I went through each of the errors raised by phpstan with the following
approach.

- If a method is part of an `@immutable` class, we can consider it pure,
  assuming it only affects internal variables.
- If a potentially pure method is calling a class's method that is only
  swapped during testing (and not during normal usage), then we can
  consider the calling method pure.
- If a class is marked deprecated, don't bother with attempting to mark
  it pure or immutable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants