Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:102822 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 59363 invoked from network); 14 Jul 2018 13:09:08 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Jul 2018 13:09:08 -0000 Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.47 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 74.125.82.47 mail-wm0-f47.google.com Received: from [74.125.82.47] ([74.125.82.47:54262] helo=mail-wm0-f47.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id EB/1D-39793-2F5F94B5 for ; Sat, 14 Jul 2018 09:09:06 -0400 Received: by mail-wm0-f47.google.com with SMTP id s9-v6so3758044wmh.3 for ; Sat, 14 Jul 2018 06:09:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:user-agent:mime-version:content-transfer-encoding:subject:to :from:message-id; bh=Ewtn5UrflDIvvhzDilMK4iWNuv8z7ezXfBiH2XSjcrk=; b=dS3seGlwC2m2EhNfE8rFh8N2Xayx9sFX8jpwH2xriw5cpptPwjHgARUFtWahbFWneR BdVYi75PQEdGc7TJ53MYTKfPVPkCxntAadt1QhF5NBm9+ZMelxdSwW4IQShH4sBXnFy1 6N5AryM1fewXpj44r9V2hnpNEFwhwt5LEJDr209Ve4dDM0cv7lk/W6jKmP+WjmvE39PL Y115JG41g+WXxCE3UrzeuMdsq9oo7bkvqI88x4Xqs2xct0flaHZJXLA/puqc6y43ikvT Ove7IxwJCkc3Qvrm68p35n7T1KGdLJ3q3udEk73r1PaOz4A1jDh/8x7gEySlSbZijpyD qRag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:user-agent:mime-version :content-transfer-encoding:subject:to:from:message-id; bh=Ewtn5UrflDIvvhzDilMK4iWNuv8z7ezXfBiH2XSjcrk=; b=pTBdUAq2vUB9PRE3MlY7ArIsy6q+6btg7p35RUdVyy9azC5eIC2Ysrom8N+xJSA8CM YbPGQ+fUoG2cFazgMstkMfKr5k5WXox/0YuRXxStgZ1CenJvH60J7uCAit/n1028nkxj u7Zj7KzYHVXQFu6wCPCSgfWgk/3hYJdsC7+qA7h5Wyj/dnE3Pne9zLuNnQppj22of26W xCnKWG6Ruh5iFI0dThAK0/rrJ9UF3f389n2gcXZFJDQy1tk8g/HAezXy++p1KTB2YJjS pDPzrKkJSGBNiDzuMkRgVLS612dIhxE9RZgNxg9wCRrYGx+FIjRyMMlWSH8vIXLVXmLR sTWA== X-Gm-Message-State: AOUpUlFLfVoj4+Mb9BvpJcQyNdqmYomBrLoE80NavlUYtLLE28DjsoPZ Z/2KoUM8TNddyudJnfoIBoTTaQAH X-Google-Smtp-Source: AAOMgpegIl+/lkN0ieAiIYAl9zTR2XRuM9Mu3CFa9yYNQ6pLPDlJ7kfW8hemxOq6p0/qV/O59jsX0Q== X-Received: by 2002:a1c:9947:: with SMTP id b68-v6mr5819241wme.159.1531573743308; Sat, 14 Jul 2018 06:09:03 -0700 (PDT) Received: from [10.176.147.223] (92.40.248.25.threembb.co.uk. [92.40.248.25]) by smtp.gmail.com with ESMTPSA id g15-v6sm19626535wrh.48.2018.07.14.06.09.02 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 14 Jul 2018 06:09:02 -0700 (PDT) Date: Sat, 14 Jul 2018 14:09:01 +0100 User-Agent: K-9 Mail for Android MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----YYGPSB74JPBHQQS51NXS7F007AUYIG" Content-Transfer-Encoding: 7bit To: internals@lists.php.net Message-ID: <8916EC21-D368-40F8-9ABD-CE0C04A73539@gmail.com> Subject: Non-nullable properties From: rowan.collins@gmail.com (Rowan Collins) ------YYGPSB74JPBHQQS51NXS7F007AUYIG Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi all, As briefly mentioned, I think the approach to non-nullable types in the ty= ped properties proposal needs more discussion, to make sure we're not repea= ting Tony Hoare's "billion-dollar mistake"=2E For parameter hints, nullability is naturally optional, particularly in PH= P where "nullable Foo" is equivalent to a union type "null or Foo"=2E For p= roperties, this isn't the case, because every property must have some initi= al state=2E The simplest solution, which I think would be a sensible starting point if= we're not ready for more complex changes, is to say that all typed propert= ies must have a default value, and if that default value is null, the type = hint must naturally be nullable=2E In other words, make "public Foo $foo" i= llegal, but allow "public ?Foo $foo=3Dnull"=2E The current RFC proposes the next simplest solution, which is to allow non= -nullable types, and trust the user to initialise them before use=2E=20 My first objection to this is that it creates an entirely new state for ob= ject properties to be in, which behaves differently from everything else in= the language=2E There will then be three or four different ways for an obj= ect property to be "unset": - not declared at all; access gives a notice and the implicit value null - declared with no default, uninitialised, implicitly null - declared with a default of null, or explicitly assigned as null - declared with a non-nullable type, never initialised; rather than an imp= licit null, access generates an Error The bigger problem is that the properties are non-nullable in name only, a= nd the declaration can't be trusted=2E Consider the following class: class Validity { public \DateTimeInterface $validFrom; public ?\DateTimeInterface $validTo =3D null; } If I have an instance $v of that class, I would expect to be able to safel= y call $v->validFrom->getTimestamp(), but need to check for nulls before do= ing the same with validTo=2E Under the current proposal, doing so will risk= errors, so I will have to check both properties before access anyway=2E Wo= rse, using is_null() or ?: will attempt to retrieve the value, so I actuall= y have to be *more* careful, and use isset() or ?? instead=2E=20 Alternatively, I can trust the author of the class, but at that point they= might as well just use a docblock - the type hint documents their intent, = but is not enforced=2E Swift is often cited as a language which gets nullability right, and a lot= of attention is given to Options, and the compiler ensuring that the None = / null case is handled; but at least as important is how it handles initial= isation of non-nullable properties, using "two-phase initialisation": https= ://docs=2Eswift=2Eorg/swift-book/LanguageGuide/Initialization=2Ehtml In short, Swift defines a specific point after which all properties must h= ave a valid value; before this point, the entire object is invalid for read= operations, so there is no need for a specific error when accessing uninit= ialised properties=2E Swift marks this point by the call to the parent initialiser, ultimately g= oing up the chain to the root object=2E PHP has no root object, and no mand= atory parent constructor calls, so would need a different way to mark this = stage=2E Constructors can already violate the rules the first phase should = impose, so we can't just use the end of the constructor as the validation p= oint=2E One possibility would be to add a new keyword like "initialize" which must= be added to constructors in the presence of non-nullable properties=2E Abo= ve that keyword, use of $this other than to write to its properties would b= e an error; afterwards, the constructor could carry on as normal=2E As I say, this is complex, and it may be best to add nullable typed proper= ties first, and give more time to try out approaches to initialisation=2E Regards, --=20 Rowan Collins [IMSoP] ------YYGPSB74JPBHQQS51NXS7F007AUYIG--