Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129575 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 633D91A00BC for ; Tue, 9 Dec 2025 15:07:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1765292873; bh=Fkc9PkN1dc/tDJaF+FeIjcm8gTUsU0FaZhIDp4l2GQU=; h=Date:Subject:To:References:From:In-Reply-To:From; b=hKJy6oin0kO2ZC6bWREPS1ot2x7ej4t5rwZ8bo4ii1/i1gx3BpkkNsF1mxsy31BBS paLUwxDnjG1O72gnq6O9HLueFHRqKwHrqzjn8thWg9/IRaYLEMxmqJppLZrpi0suZf i3brGRRhP3+IVFOcIn4ca/doV4adZsOMiwIlG27Qg+F8XKcFBTjHwBstz1/Cmz+EkJ rDl0nQTBV4YIcVpU4ZWODyQZdi2FOMMraD7C3ygNwrC22+0Wjpas1nH+fLIbz9aUlh cNn1Ex3STu51SnvI9oErg8nSwOO8I6AzxMGlcBRsycTR0n3hYdipHVT+FF1x7XmS8/ AaYi9t2akzO0Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A74461801D8 for ; Tue, 9 Dec 2025 15:07:51 +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=-0.9 required=5.0 tests=BAYES_20,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-b8-smtp.messagingengine.com (fhigh-b8-smtp.messagingengine.com [202.12.124.159]) (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 ; Tue, 9 Dec 2025 15:07:51 +0000 (UTC) Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.stl.internal (Postfix) with ESMTP id 4AB927A003C for ; Tue, 9 Dec 2025 10:07:45 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Tue, 09 Dec 2025 10:07:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-transfer-encoding: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=fm1; t=1765292865; x=1765379265; bh=s91d5lL/01I0B5hi5Awmx7GhDKwKD6h3BKB//b6BcTI=; b= qwJpWCEYjGAO4AVE8Jw0jP/rrehFN0z/2WE1rAWQXmTq0NqvWTO/11tddxzBkntP VVir2kCmXa+4zvMvgHdXfbqfV/E+2xEJncfblNAC5lU4/kXRHnUX0KMhImkonlpb WjDYK839XHT89wW85e0lMmCYVK2gxcQR1aCKGT5u2wKSOEAMxawyL9lOD5krVbFV 9keLfJfDUDTIptWbXkgxzTHx3yE3W5zasKw0CReO0z9qmDbSjuyrru4awBuk9f7f QBaH7RbQMejfXLTqWc57Fb7YPOO7UeDGxe4huzDFYRK0RcOYe618g9YaDXv1YrYj 1pUAB7upPJp6pwfeDMIUEQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding: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=fm1; t=1765292865; x=1765379265; bh=s 91d5lL/01I0B5hi5Awmx7GhDKwKD6h3BKB//b6BcTI=; b=TLA4tUfVsvw2dfZ0U ysRvINR30SPouzzJtcfMj/0F9Ga+6pp7Qk9ySGOEAzy+xm0F0tY5bUi31KN7hlAu MGqWIMXEsI0wEpLecDST7hwzQqjpBd43an7bpweJunnvIwhk9fn/xwB+zTpR2LZq OOltKNr8MAqrJ80eWD1fc98/6ocSng2RHWBc61fLKgWKRpo3EUK1sr0M2btxxI9f eaaG3Pjn4drcCukUIPBZ/zlGaqX7IgxilAg724+2m3i6ERyPIavCJGZ2EMPf0miN AGK9TTn61AJDe0TdUZQuVgtH8ort1wBjDzTBzU8+Jrmzr6CdyPnUaDOyed4NFiVy dSmhQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgdduleekkecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecunecujfgurhepkfffgggfuffvfhfhjggtgfesthekredttd dvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhinhhsucglkffoufhorfgnfdcuoehi mhhsohhprdhphhhpsehrfigvtgdrtghordhukheqnecuggftrfgrthhtvghrnheptdektd evtddvffejhedtledtudefkeehteeiueeiudekleejjedvtefhjedtffevnecuffhomhgr ihhnpehsthgrtghkohhvvghrfhhlohifrdgtohhmnecuvehluhhsthgvrhfuihiivgeptd enucfrrghrrghmpehmrghilhhfrhhomhepihhmshhophdrphhhphesrhifvggtrdgtohdr uhhkpdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuthdprhgtphhtthhope hinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Tue, 9 Dec 2025 10:07:44 -0500 (EST) Message-ID: <3820f37e-1d9d-46f3-90ea-9fa3d8c3465e@rwec.co.uk> Date: Tue, 9 Dec 2025 15:07:43 +0000 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] Proposal discussion: distinguishing "never assigned" vs "assigned null" To: internals@lists.php.net References: Content-Language: en-GB In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") On 09/12/2025 13:59, Hichem Taboukouyout wrote: > Hello Internals of PHP, > > I’d like to get feedback on a potential language feature before > considering whether it deserves an RFC. > > Currently, PHP does not provide a general way to distinguish between: > - a variable or property that has never been assigned, and > - one that was explicitly assigned the value null. Hi Hichem, This is something which has been discussed several times over the years, and consensus has generally been against. My own view is largely unchanged since I wrote these two Stack Overflow answers a decade ago: https://stackoverflow.com/a/18646568/157957 and https://stackoverflow.com/a/18601583/157957 In short: any algorithm which needs to distinguish between "never assigned" and "currently contains null" can and should be rewritten to instead use some other distinction - a separate boolean tracking the state, or additional values which can be distinguished directly. Key-value maps built with associative arrays or dynamic objects are an exception to this rule, but we already have array_key_exists and property_exists for those use cases. One thing that has changed is that we now have native, opaque, enums; so many cases assigning specific meaning to null can be rewritten to be more expressive. For example, instead of this: ``` /** @var ?string $inputFile */ if ( $inputFile === null ) {     // do something with standard input } else {     // verify and use the given input file in some way } ``` You can write this: ``` enum InputFileOption { case STDIN; } /** @var string|InputFileOption $inputFile */ if ( $inputFile === InputFileOption::STDIN ) {     // do something with standard input } else {     // verify and use the given input file in some way } ``` Then instead of wanting a new "very null" check: ``` /** @var ??string $inputFile */ if ( ! is_assigned($inputFile) ) {     // complain that the user didn't provide an answer } else if ( $inputFile === null ) {     // do something with standard input } else {     // verify and use the given input file in some way } ``` You can just add a case to the enum: ``` enum InputFileOption { case STDIN; case NOT_CONFIGURED; } /** @var string|InputFileOption $inputFile */ if ( $inputFile === InputFileOption::NOT_CONFIGURED ) {     // complain that the user didn't provide an answer } else if ( $inputFile === InputFileOption::STDIN ) {     // do something with standard input } else {     // verify and use the given input file in some way } ``` And unlike using "null" and "unassigned" for your special states, you can carry on adding more cases whenever you want. Regards, -- Rowan Tommins [IMSoP]