Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128017 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 944791A00BC for ; Sat, 12 Jul 2025 20:31:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1752352161; bh=xre3SilvrNqZ9n/iulQ0ovn3X5O7Uo6aMP4qqXbKTo4=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=BapH0Q1xhbx+P3V4yJz1HOBb4iwJF6/GQ9Ow1UHUjVHFQHnO0F0CSZl+/XdIDxPPB +rpfPkks4qbcErtIjx6WohVP1mc11HBJqDF3Dr7NubPuHZphx7DJhhoLejtn60GMk2 FvI64tCx4jXttp68CWrbbLt5Ov1yQunnLqWfiQw05xBb9AtJU8Womjocwbse8WZ+BZ pQxEer+AivZP/0rTuX8p8f3aDQ4dW6L30Cyo6LvygkODeZE0uCjkrJL9bpwwv+Qu3p qWnDSDrlQz8u0s9ZHrWI0g1XMZbHvG2oYrwmcePt4g+zBADt6DDIe4J47ktvEsXmg1 I96Lhi55+YU3A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 232CC18004E for ; Sat, 12 Jul 2025 20:29:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from fout-a2-smtp.messagingengine.com (fout-a2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 12 Jul 2025 20:29:17 +0000 (UTC) Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfout.phl.internal (Postfix) with ESMTP id C296CEC0280; Sat, 12 Jul 2025 16:31:05 -0400 (EDT) Received: from phl-imap-05 ([10.202.2.95]) by phl-compute-05.internal (MEProxy); Sat, 12 Jul 2025 16:31:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1752352265; x= 1752438665; bh=76a4iq/70uiqMV5xr37CfDrSfRxxbbQU7u++CT9ZfQs=; b=E 8Yr7MT4+mtAsT6ZBZ2d84yNhRgNQNTWENnUjWFTCSQaAdmkavKmlZq4I8fGsp8gI KJaT9r5FClkAnRCL3Gb0ya3sB9uHymuFPTvR4jo8Z9aSNkLgxQO4J4jECtqq4cUL TFGeRqjIA/0yBIj58ISU3acn8wu2Nif+zLiFjnjO8Ddqh8Z36DW59VJ5h78vpZCN LNlpMqbb0VEAft9ZFPJ1anZeNJeTv8XadFCCJnlQM2RakK1py6ibLwlnQQ1tvW22 CS8y5A8jALU9cGOzq0FpYxHe/8Q7G9odMStyNMYGrXNFGzzi2paFgELIz9petMZy GV9/CVc8r/WzpufTsQ68g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1752352265; x=1752438665; bh=76a4iq/70uiqMV5xr37CfDrSfRxxbbQU7u+ +CT9ZfQs=; b=GhsoEF+oI2trKYGgr2VUYJ5kNnyQ8Bu8MsjldtL7XRrNKQmjJgp BHWTsLHvV1jp3y0Cv5Bq5O6c2G6MAIs/JKNr2DYom5a7RfCYHJ8fBev3ajntkNrU V6pBcTPIUYNccNil4Sr2RaJXQqDjWmCMZZa+hYM0NVw74rHKOLPm+aKrQuvUBT5I ymicDbHSEeA+Dv/0JFd7CjhhHsulaWIXYURZG+aU7160TR3ejxohzCyYz2PgGXZY I2WLjOD7iYBdqOjMAuEF53xsEqB4T/EKGg5gpQa96SbBk4TiGl5AKPh3i8n5fEMo 2Upt2mcm+NQSLXy829jKl+3tH5XlEU6VMrw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgdegjeduiecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjug hrpefoggffhffvvefkjghfufgtsegrtderreertdejnecuhfhrohhmpedftfhosgcunfgr nhguvghrshdfuceorhhosgessghothhtlhgvugdrtghouggvsheqnecuggftrfgrthhtvg hrnhepieeuteehvddvfeejhffgieehleehhedthfefkeejffelgfevvdekudetjeejtddt necuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprhhosg essghothhtlhgvugdrtghouggvshdpnhgspghrtghpthhtohepgedpmhhouggvpehsmhht phhouhhtpdhrtghpthhtohepnhhitgholhgrshdrghhrvghkrghsodhphhhpsehgmhgrih hlrdgtohhmpdhrtghpthhtohepihhnthgvrhhnrghlshesghhpsgdrmhhovgdprhgtphht thhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvghtpdhrtghpthhtohepth hhvghoughorhgvjhgssehouhhtlhhoohhkrdgtohhm X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 264A11820074; Sat, 12 Jul 2025 16:31:05 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: T93bbdd38331b9ecb Date: Sat, 12 Jul 2025 22:29:26 +0200 To: "Theodore Brown" , "Gina P. Banyard" , "Nicolas Grekas" Cc: "PHP internals" Message-ID: <4df0afe8-9809-4420-8158-48cf633bccfd@app.fastmail.com> In-Reply-To: References: <3Yl0UGauXmKqk7s7Hqbv6iaXru-hZHf8Wj6VjwwihgRSaqZo5EZ2ndsOle-ae41C-lvnirynWt6PpuD7UJPL0zPCw18QHFE81Eb--fiiEbc=@gpb.moe> Subject: Re: [PHP-DEV][RFC] Deprecate type juggling to and from bool type within the function type juggling context Content-Type: multipart/alternative; boundary=d3cff7b818324346abf24501efc4bda5 From: rob@bottled.codes ("Rob Landers") --d3cff7b818324346abf24501efc4bda5 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sat, Jul 12, 2025, at 01:29, Theodore Brown wrote: > On Fri, July 11, 2025 at 05:00 G. P. Banyard wrote: >=20 > >> On Monday, 30 June 2025 at 10:26, Nicolas Grekas wrote: =20 > >> ... =20 > >> 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, explic= it 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 improve= ment 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). >=20 > From my experience there is a very real benefit to deprecating both ca= st-from-bool and cast-to-bool. > Let me give an example of both. >=20 > Recently had to fix some legacy code where the result of `filemtime` w= as 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 resu= lt in the script continuing with bad > data instead of halting with a type error. >=20 > Cast-to-bool can cause the same kinds of issues, which are sometimes e= ven harder to notice. Consider the following: >=20 > function processArray(array $items, bool $hasCertainKey) { ... } >=20 > $keyOrFalse =3D array_search('my value', $items); >=20 > processArray($items, $keyOrFalse); >=20 > 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, w= hen 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. >=20 > I believe deprecating type juggling to/from bool will help avoid creat= ing bugs like this (and likely > surface existing ones that should be fixed). >=20 > 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 with= out realizing they're in a worse situation than using non-strict mode. L= ike `((int)"123password") =3D=3D=3D 123`, however attempting to coerce t= hat 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 j= ust be rewritten as `gmdate((int)filemtime($file))` without a second tho= ught. In your other example showing the difference in array_search, I also hig= hly 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 exp= ecting bool" and/or "you are casting int|string to bool, check that (boo= l)"0" won't be an edge-case; consider using empty() instead"). =E2=80=94 Rob --d3cff7b818324346abf24501efc4bda5 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


On Sat, Jul 12, 2025, at 01:29, Theodore Brown wrote:<= /div>
On Fri, July 11= , 2025 at 05:00 G. P. Banyard wrote:

>> O= n Monday, 30 June 2025 at 10:26, Nicolas Grekas wrote:  
=
>> ...  
>> The latter, cast-from-b= ool, I think they're all useful improvements. While most likely harmless= in all the specific
>> cases of the PR, doing e.g. an s= trpos() 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 "bo= ol" or "(bool) ($this->loggedErrors & $type)" are a clear downgra= de: 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
>&= gt; expressions with e.g. the "if ()" operator, which doesn't need the e= xplicit cast (and shouldn't of course).

From my= experience there is a very real benefit to deprecating both cast-from-b= ool and cast-to-bool.
Let me give an example of both.

Recently had to fix some legacy code where the result o= f `filemtime` was being passed to `gmdate` to format
the modif= ication timestamp. `filemtime` returns false on failure, but this is sil= ently coerced to zero
(a valid timestamp) when passed to the i= nt 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 ev= en harder to notice. Consider the following:

&n= bsp;   function processArray(array $items, bool $hasCertainKey= ) { ... }

    $keyOrFalse =3D ar= ray_search('my value', $items);

  &nb= sp; processArray($items, $keyOrFalse);

It's ver= y easy to miss the bug in this code, especially since it seems to functi= on 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 w= ill be silently
coerced to false and the array will be incorre= ctly processed as though the value is not in the array.

I believe deprecating type juggling to/from bool will help avoi= d creating bugs like this (and likely
surface existing ones th= at should be fixed).

Kind regards,
Th= eodore

I'm not so confident that w= ill be the case. In lots of strict-mode code I've worked with over the y= ears, people tend to blindly cast things without realizing they're in a = worse situation than using non-strict mode. Like `((int)"123password") =3D= =3D=3D 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 cas= es, 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 functio= n's expectations. ("you are passing int|string to a function expecting b= ool" and/or "you are casting int|string to bool, check that (bool)"0" wo= n't be an edge-case; consider using empty() instead").
=E2=80=94 Rob
--d3cff7b818324346abf24501efc4bda5--