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

Reply via email to