Skip to content

Fix Seq::unique to use strict type-sensitive comparison#80

Merged
lippserd merged 1 commit into
mainfrom
seq
Jun 24, 2026
Merged

Fix Seq::unique to use strict type-sensitive comparison#80
lippserd merged 1 commit into
mainfrom
seq

Conversation

@lippserd

Copy link
Copy Markdown
Member

The original implementation stored non-object values as PHP array keys, which silently coerce scalar types, causing type-distinct values to collide. Objects were tracked by spl_object_hash, so a string holding the same hash would accidentally match.

The fix uses SplObjectStorage for object identity and in_array in strict mode for all other values, preserving type distinctions across scalars, arrays, and resources.

The original implementation stored non-object values as PHP array keys,
which silently coerce scalar types, causing type-distinct values to
collide. Objects were tracked by `spl_object_hash`, so a string holding
the same hash would accidentally match.

The fix uses `SplObjectStorage` for object identity and `in_array` in
strict mode for all other values, preserving type distinctions across
scalars, arrays, and resources.
@lippserd lippserd added this to the v1.0.0 milestone Jun 22, 2026
@cla-bot cla-bot Bot added the cla/signed label Jun 22, 2026

@BastianLedererIcinga BastianLedererIcinga left a comment

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.

I had discussed a similar approach using in_array() with @nilmerg, while working on the previous implementation, but we agreed on the hashmap to prioritize performance.
If you consider the added test cases necessary the previous implementation is of course not sufficient.

An idea I had when working on the original implementation was a separate cache per scalar type. It would certainly clutter the code a bit, but it would allow us to prevent quadratic runtime for these types, while keeping type-sensitive comparison.

If you think that's overkill I'm fine with that, but I'd like you to consider the idea, since we don't know where this function will be used in the future.

@lippserd

Copy link
Copy Markdown
Member Author

I had discussed a similar approach using in_array() with @nilmerg, while working on the previous implementation, but we agreed on the hashmap to prioritize performance.
If you consider the added test cases necessary the previous implementation is of course not sufficient.

Sure it is slower. But does it matter? Do we call this method always with 1k+ items? Is it used in hot paths? If yes, we must of course change the implementation again. But I absolutely consider the test cases necessary, else this method is just a lie and breaks valid usages.

If you think that's overkill I'm fine with that, but I'd like you to consider the idea, since we don't know where this function will be used in the future.

Do we have other code than Icinga Notifications Web that uses this function/could use this function? If not, I would not have introduced this method as a library function and would have implemented the limited version in the module.

@lippserd lippserd merged commit be9dc61 into main Jun 24, 2026
13 checks passed
@lippserd lippserd deleted the seq branch June 24, 2026 16:31
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.

2 participants