Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:121778 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 40280 invoked from network); 23 Nov 2023 12:29:38 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 23 Nov 2023 12:29:38 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 009CE18004B for ; Thu, 23 Nov 2023 04:29:42 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, FREEMAIL_REPLY,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f179.google.com (mail-yb1-f179.google.com [209.85.219.179]) (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 ; Thu, 23 Nov 2023 04:29:41 -0800 (PST) Received: by mail-yb1-f179.google.com with SMTP id 3f1490d57ef6-da3b4b7c6bdso810122276.2 for ; Thu, 23 Nov 2023 04:29:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700742576; x=1701347376; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=pwl8ZN/ApoT/Dp7rjPMrofezCg5j4T2U5iLDHi9NjnU=; b=iV3V03sEdU8mNgHOO7mAyQCxzeDqEnvWBkyJ7/sAKp7yj4j14mKsyV3M1t5CyZdzPV ZLkE358w2dFSP91hSVA1yj6feQsdo+aJzrSB+T2bTGFGvRY559fRRXGdqYxvlMb9lUbj EuhgVFgkdMru7e5nExMTW8u1IK5eigeAUQEMwoAO9exTYeuFFLRae35Jwl4Ex5ObchDb cKCTYkikGpzjL9Mpm/7efUT7MUuR+J9jh0WceYhaCgcLInvkM1pagT0UcCBj6lGH1kV2 P93tAeeOT1L/ysbd2Z1NqiA2L8M+L6rlF1ixOwPsmMf2FCD5fHhA6aO3OVzjycMt1DZd osTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700742576; x=1701347376; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pwl8ZN/ApoT/Dp7rjPMrofezCg5j4T2U5iLDHi9NjnU=; b=LxF8ADVB9H/20mH3NExoW9c5Q8bvdpWDe6ZZ1tNSol5YjOjFojUNWEQnIp42mrkdHX sFwJVupubaMxFsIIlzlyj7wUlcoLZldBFJrjYL3fW5M62yo60gX+cdp2K4gIpGBrgU38 Td3P6WiSjzKiNKLfn0h7bY24ZttuHSysaWS8+be/GPT3nRb8Qd5Kp0ok936lJvbxu8B0 QoLO0ezqXsa601u1Wcma16ckrmAl34AgHKVcYEF9ygd/ePhexh9t6FELBqE6GnEOzdUL vfmx9Jpl0ADsqQ9Ktkxl4zid3whpGETxlS8Ckh0qEQHGvq62kjeQyGhdN5zydSNbDnLh 8bEA== X-Gm-Message-State: AOJu0YzRCvJYxPA4Cn4ImPdsFvmgFROhyEfO17I0m20aIEi54f1f8Aua 42vx5CjcCn+4sXfu6MmOLSOEV6OVTkZdiQJhdIpkK5M0eak= X-Google-Smtp-Source: AGHT+IEK/Bzr2xSAfgBooVOtsMAtpL/f0AFfxA6NpC0MKa62aZmzYd7yES10psAqHs4ADfvWNexXwe+Oyyq/dzYk3gU= X-Received: by 2002:a5b:c0d:0:b0:d9a:5630:5281 with SMTP id f13-20020a5b0c0d000000b00d9a56305281mr5080135ybq.62.1700742576479; Thu, 23 Nov 2023 04:29:36 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Thu, 23 Nov 2023 12:29:24 +0000 Message-ID: To: PHP Internals Content-Type: multipart/alternative; boundary="0000000000002024bf060ad0fd09" Subject: Re: [PHP-DEV] Re: [RFC][Discussion] Harmonise "untyped" and "typed" properties From: rowan.collins@gmail.com (Rowan Tommins) --0000000000002024bf060ad0fd09 Content-Type: text/plain; charset="UTF-8" On Thu, 23 Nov 2023 at 08:48, Nicolas Grekas wrote: > Sorry this comes as a surprise to you but you're rewriting history here. > The current behavior, the one that was fixed in that commit, matches how > PHP behaved before typed properties, so this commit brought consistency. > The question of "what does __get do with a property that has been declared but not assigned a value?" has no answer before PHP 7.4, because that situation simply never happened. So there isn't really one answer to what is "consistent". If I understand rightly, your position, and Nikita's, is that the behaviour should be consistent with the statement "if you have declared a property, access doesn't trigger __get unless you explicitly call unset()". This is what the change that slipped into 7.4.1 "fixed". The reason it surprised me is that I expected it to be consistent with a different statement: "if you have an __get method, this takes precedence over 'undefined variable' notices/warnings/errors". That statement was true in 7.3, and still true in the original implementation in 7.4.0 (including "unitialized" alongside "undefined"), but was *broken* by the change in 7.4.1: now, the "uninitialized property" error takes precedence over __get in the specific case of never having assigned a value. > About the behavior, it's been in use for many years to build lazy proxies. > I know two major use cases that leverage this powerful capability: Doctrine > entities and Symfony lazy services. There are more as any code that > leverages ocramius/proxy-manager relies on this. > Just to be clear, it is not the behaviour *after* calling unset which I am concerned about, it is the behaviour *before* calling unset or assigning any value. I was aware of the interaction with __get, but wrongly assumed that the rule was simply "uninitialized properties trigger __get". > About the vocabulary, the source tells us that "uninitialized" properties > that are unset() become "undefined". I know that's not super accurate since > a typed property is always defined semantically > Just "undefined" is not sufficiently unambiguous; you have to distinguish four different states: 1) Never declared, or added dynamically and then unset 2) Declared without a type, then unset 3) Declared with a type, not yet assigned any value 4) Declared with a type, then unset The messages presented to the user refer to both (1) and (2) as "undefined", and both (3) and (4) as "uninitialized". As it stands, the RFC would replace all instances of (2) with (4), but that still leaves us with two names for three states. Claude Pache wrote: > However, it is not a problem in practice, because users of classes implementing (1) but not (2) do not unset declared properties, ever. Nikita Popov wrote: > ... and then forbid calling unset() on declared properties Right now, unset() is also the only way to break a reference, other than another assign-by-reference, so it's quite reasonable to write "unset($this->foo)" instead of "$this->foo" to ensure a property is truly reset to a known state. Maybe we need a new function or operator to atomically break the reference and assign a new value, e.g. unreference($this->foo, 42); or $this->foo := 42; to replace unset($this->foo); $this->foo=42; Regards, -- Rowan Tommins [IMSoP] --0000000000002024bf060ad0fd09--