-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Duplicates returned by array_unique when using enums #9775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This would be because enums aren't comparable - not even backed ones, apparently. var_dump(Test::COURSES_ADMIN <=> Test::COURSES_ADMIN); // 0
var_dump(Test::COURSES_ADMIN <=> Test::COURSES_REPORTING_ACCESS); // 1
var_dump(Test::COURSES_REPORTING_ACCESS <=> Test::COURSES_ADMIN); // 1 Equality is supported but inequality is not. Functions like sort($data, SORT_REGULAR);
var_dump($data);
If you try $data = array_unique($data, flags: SORT_REGULAR);
The RFC and docs say that "basic" (not backed) enums aren't comparable, however no statement is made about comparisons of backed enums. Seems like the fix is to implement inequality comparisons for them... |
The implementation of array_unique is based on assumption that everything are comparable, which is true in the past. However this should be considered as an optimization for time complexity, not a requirement for using that function. If enum (no matter backed or not) is designed to be not comparable, which I'm also favor of, then we may choose to modify the implementation of array_unique to make sure it works as expected. To support comparations for backed enum is another topic (with RFC). |
And I think this is the actual problem, namely that PHP allows to compare apples and oranges and yields seemingly correct results. Such operations should at least raise a warning (and maybe even an
Hmm, not sure that is really necessary, since this is already possible with some userland code, e.g. https://3v4l.org/4uv5s. |
The problem is indeed that It might make sense to introduce a new mode that does a 1:1 comparison with values that have already been added to the result set (or make this a new function, although that might be interpreted as the "better"/faster version which is not the case if the size of the array is big enough). |
Created a quick implementation here: #9788 |
Couldn't agree more. We should not sliently return false without saying anything, this may lead to hidden bugs.
It's still a bit different. Users are fully aware of what they are doing in your example, but when we do that, we need clearer rules. Considering following example, if we simply use the backed value for comparision, enum TypeA: int {
case foo = 1;
case bar = 2;
}
enum TypeB: int {
case foo = 1;
case bar = 2;
}
$arr = [TypeA::foo, TypeB::foo, TypeA::foo, TypeB::bar];
var_dump(array_unique($arr, flags: SORT_REGULAR)); |
@iluuu1994 I wonder, for the specific case of enum values, can the sorting of array_unique (after all, it has it's own compare functions, which in turn call the zend functions - these could just be changed accordingly) not just be extended so that these are special cased and e.g. "greater" than all other values, but between each other simply the pointer is compared? The identity check is just a bandaid I'd say, and far more general. But I would expect array_unique to just work on enum values. |
I would say the opposite, fixing enums for this case seems like a bandaid. I'd prefer having an |
@bwoebi |
@iluuu1994 I was thinking of rewriting the logic of array_unique to use |
Uh oh!
There was an error while loading. Please reload this page.
Description
The following code:
Resulted in this output:
But I expected this output instead:
Quick preview:
https://3v4l.org/f3XVY#v8.1.11
PHP Version
PHP 8.1.11, 8.2rc3
Operating System
No response
The text was updated successfully, but these errors were encountered: