On Sat, Jul 12, 2025, at 01:29, Theodore Brown wrote:
> On Fri, July 11, 2025 at 05:00 G. P. Banyard wrote:
>
> >> On Monday, 30 June 2025 at 10:26, Nicolas Grekas wrote:
> >> ...
> >> The latter, cast-from-bool, I think they're all useful improvements. While
> >> most likely harmless in all the specific
> >> cases of the PR, doing e.g. an strpos() on false feels hardly legit. I'm
> >> therefore sympathetic to making these changes.
> >>
> >> For cast-to-bool, I'm WAY less convinced. From the PR above, explicit
> >> casts like "return (bool) preg_match(...)"
> >> on a method that returns a "bool" or "(bool) ($this->loggedErrors &
> >> $type)" are a clear downgrade: it makes the
> >> typing PHP just more verbose without any real benefit. That doesn't look
> >> worth asking the whole ecosystem to fix
> >> those deprecations. It is especially hard to see this as an improvement
> >> when comparing to using the same
> >> expressions with e.g. the "if ()" operator, which doesn't need the
> >> explicit cast (and shouldn't of course).
>
> From my experience there is a very real benefit to deprecating both
> cast-from-bool and cast-to-bool.
> Let me give an example of both.
>
> Recently had to fix some legacy code where the result of `filemtime` was
> being passed to `gmdate` to format
> the modification timestamp. `filemtime` returns false on failure, but this is
> silently coerced to zero
> (a valid timestamp) when passed to the int parameter, which would result in
> the script continuing with bad
> data instead of halting with a type error.
>
> Cast-to-bool can cause the same kinds of issues, which are sometimes even
> harder to notice. Consider the following:
>
> function processArray(array $items, bool $hasCertainKey) { ... }
>
> $keyOrFalse = array_search('my value', $items);
>
> processArray($items, $keyOrFalse);
>
> It's very easy to miss the bug in this code, especially since it seems to
> function correctly as long as 'my value'
> is not in the array, or is not the first item in the array. However, when
> it's at index 0 the key will be silently
> coerced to false and the array will be incorrectly processed as though the
> value is not in the array.
>
> I believe deprecating type juggling to/from bool will help avoid creating
> bugs like this (and likely
> surface existing ones that should be fixed).
>
> Kind regards,
> Theodore
I'm not so confident that will be the case. In lots of strict-mode code I've
worked with over the years, people tend to blindly cast things without
realizing they're in a worse situation than using non-strict mode. Like
`((int)"123password") === 123`, however attempting to coerce that string to an
int results in a proper type error in non-strict mode.
That is to say, I highly suspect that `gmdate(filemtime($file))` would just be
rewritten as `gmdate((int)filemtime($file))` without a second thought.
In your other example showing the difference in array_search, I also highly
suspect people would just cast it to bool without noticing the 0-key edge case.
Both cases, I believe, can simply be solved by tooling highlighting when you're
passing a union type to a function that doesn't overlap with the function's
expectations. ("you are passing int|string to a function expecting bool" and/or
"you are casting int|string to bool, check that (bool)"0" won't be an
edge-case; consider using empty() instead").
— Rob