Skip to content
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

has every arrow function parameter seems to be equal to everything #3923

Open
ericmorand opened this issue Dec 2, 2023 · 4 comments
Open

Comments

@ericmorand
Copy link
Contributor

ericmorand commented Dec 2, 2023

{{ (5 has every v => v == 4 and v == "foo") ? 'Every' : 'Not every' }} v is equal to both 4 and "foo"

Outputs:

Every v is equal to both 4 and "foo"

https://twigfiddle.com/0qaa9i

How can every v be equal to both 4 and "foo"?

That v is equal to one of them would be legit, but how can it be equal to both of them_? 4 is not equal to "foo" - either in PHP or Twig, so what is happening here?

Is this a bug? This is very hard to tell since there doesn't seem to be any documentation about the behavior of this operator outside of arrays.

@ericmorand ericmorand changed the title has every operators return true when applied to number or string or boolean has every arrow function parameter seems to be equal to everything Dec 2, 2023
@GromNaN
Copy link
Contributor

GromNaN commented Dec 2, 2023

You may have a PHP warning telling "Warning: foreach() argument must be of type array|object, int given". Since the int can't be iterated, the default value is returned, which is true.

function twig_array_every(Environment $env, $array, $arrow)
{
twig_check_arrow_in_sandbox($env, $arrow, 'has every', 'operator');
foreach ($array as $k => $v) {
if (!$arrow($v, $k)) {
return false;
}
}
return true;
}

@ericmorand
Copy link
Contributor Author

ericmorand commented Dec 2, 2023

I'm questioning the language specification itself, not the implementation.

The implementation was written the way it is written to honor the specification. Would the specification have established that "it is not possible to use the has every operator on anything else than an iterable", a runtime error would have been thrown by the implementation.

But since the implementation doesn't throw an error - and thus allows non-iterable values to be operand of the operator, it means that the specification says that it is allowed. That's why my question is about the rational of this specification and especially the one that drives the assertion "in the body of the arrow function of the has every operator, the parameters are equal to everthing".

If this is what the specification says, then the implementation is fine. But I think it needs to be explained in the documentation because it makes this operator unpredictable from a consumer point of view.

And from the point of view of the teams that implement the language and that have no way to know if there implementation is correct or not.

@ericmorand
Copy link
Contributor Author

ericmorand commented Dec 2, 2023

The has every operator seems to be all over the place:

{{ 5 has every "whatever" }}
{{ 5 has every true }}
{{ 5 has every null }}
{{ 5 has every false }}
{{ 5 has every (5 == 3) }}

Outputs:

1
1
1
1
1

What is the exact accepted syntax of this operator? And what is its purpose? Why does it accept basically anything as second operand?

@GromNaN
Copy link
Contributor

GromNaN commented Dec 3, 2023

If it's not covered by a test, it's just an edge case, not a specific feature. There isn't type hint on the argument because iterable type did not exist when Twig was created, and it was not added after.
The PHP warning is a clear indicator that you are not calling the function correctly. But I'm sure we can improve it.

What do your think should be the correct behavior? Throw a Type error, return true or false, or call the callback with the single value?

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

No branches or pull requests

2 participants