Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:102823 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 63318 invoked from network); 14 Jul 2018 14:37:58 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Jul 2018 14:37:58 -0000 Authentication-Results: pb1.pair.com header.from=levim@php.net; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=morrison.levi@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.215.51 as permitted sender) X-PHP-List-Original-Sender: morrison.levi@gmail.com X-Host-Fingerprint: 209.85.215.51 mail-lf0-f51.google.com Received: from [209.85.215.51] ([209.85.215.51:38529] helo=mail-lf0-f51.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id EA/8D-39793-FBA0A4B5 for ; Sat, 14 Jul 2018 10:37:53 -0400 Received: by mail-lf0-f51.google.com with SMTP id a4-v6so29286146lff.5 for ; Sat, 14 Jul 2018 07:37:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=Wyux9fXa2RELQVq+r0djw1UNtypVGeGkwhuB+AmhxNo=; b=XnRua56zt913foQtOFEJ3sxkBvqDsRJAH/seGkTt+QO++J1FOgpoidoxPXVlmh9nEJ kDcCoWQ/M0Q6S1GHBCf28t7WiSWCzv2qmiopGZJ29A89rK7vyAdoeaMQReUnIHhN7a/7 shhquH5oY1iWCCQfGxC7X36STPJ0hkfIF8DQPbIG69Czmy8EovC6BpyAYPFE3ovyW8oM OL15LzVsvHhAQPHtnpGqe4XbQVjkTBcfenQLhpIVXavN0YqoJRA1F8RVPwdQrW92iK/8 MUXOUkSJz3mEw0kxwFC3s/fQlLNh+ltcKade4nykKAHw6aW/cXSC/mXbiuYKh2mN4Mq8 GV5Q== X-Gm-Message-State: AOUpUlEEYnOkOJXBuxC9+RFpRi4g9gVBFIxXgrpvevRxSjrt1n+dcNdR 2tnxDGWzoFOdOjtxe96Uc7LMIueysEAm9RxRyes= X-Google-Smtp-Source: AAOMgpd8EyKwKBvz9qlhqX1MDmce/HxuK35QOdgPrS/oZSsmIyQH7prXHNk79/wY3hyHuBfcMoE9qsO5gIER2x69fSM= X-Received: by 2002:a19:5d54:: with SMTP id p20-v6mr7456065lfj.143.1531579067592; Sat, 14 Jul 2018 07:37:47 -0700 (PDT) MIME-Version: 1.0 References: <8916EC21-D368-40F8-9ABD-CE0C04A73539@gmail.com> In-Reply-To: <8916EC21-D368-40F8-9ABD-CE0C04A73539@gmail.com> Date: Sat, 14 Jul 2018 08:37:32 -0600 Message-ID: To: Rowan Collins Cc: internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] Non-nullable properties From: levim@php.net (Levi Morrison) On Sat, Jul 14, 2018 at 7:09 AM Rowan Collins wro= te: > > Hi all, > > As briefly mentioned, I think the approach to non-nullable types in the t= yped properties proposal needs more discussion, to make sure we're not repe= ating Tony Hoare's "billion-dollar mistake". > > For parameter hints, nullability is naturally optional, particularly in P= HP where "nullable Foo" is equivalent to a union type "null or Foo". For pr= operties, this isn't the case, because every property must have some initia= l state. > > The simplest solution, which I think would be a sensible starting point i= f we're not ready for more complex changes, is to say that all typed proper= ties must have a default value, and if that default value is null, the type= hint must naturally be nullable. In other words, make "public Foo $foo" il= legal, but allow "public ?Foo $foo=3Dnull". > > The current RFC proposes the next simplest solution, which is to allow no= n-nullable types, and trust the user to initialise them before use. > > My first objection to this is that it creates an entirely new state for o= bject properties to be in, which behaves differently from everything else i= n the language. There will then be three or four different ways for an obje= ct 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 im= plicit null, access generates an Error > > The bigger problem is that the properties are non-nullable in name only, = and the declaration can't be trusted. Consider the following class: > > class Validity { > public \DateTimeInterface $validFrom; > public ?\DateTimeInterface $validTo =3D null; > } Even if this had a constructor we couldn't "trust" it because there are ways to skip constructors. > If I have an instance $v of that class, I would expect to be able to safe= ly call $v->validFrom->getTimestamp(), but need to check for nulls before d= oing the same with validTo. Under the current proposal, doing so will risk = errors, so I will have to check both properties before access anyway. Worse= , using is_null() or ?: will attempt to retrieve the value, so I actually h= ave to be *more* careful, and use isset() or ?? instead. > > Alternatively, I can trust the author of the class, but at that point the= y might as well just use a docblock - the type hint documents their intent,= but is not enforced. > > > Swift is often cited as a language which gets nullability right, and a lo= t 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 initia= lisation of non-nullable properties, using "two-phase initialisation": http= s://docs.swift.org/swift-book/LanguageGuide/Initialization.html > > In short, Swift defines a specific point after which all properties must = have a valid value; before this point, the entire object is invalid for rea= d operations, so there is no need for a specific error when accessing unini= tialised properties. > > Swift marks this point by the call to the parent initialiser, ultimately = going up the chain to the root object. PHP has no root object, and no manda= tory parent constructor calls, so would need a different way to mark this s= tage. Constructors can already violate the rules the first phase should imp= ose, so we can't just use the end of the constructor as the validation poin= t. > > One possibility would be to add a new keyword like "initialize" which mus= t be added to constructors in the presence of non-nullable properties. Abov= e that keyword, use of $this other than to write to its properties would be= an error; afterwards, the constructor could carry on as normal. > > > As I say, this is complex, and it may be best to add nullable typed prope= rties first, and give more time to try out approaches to initialisation. Again, as constructors can be skipped this solution does little to ensure validity. The approach from the RFC is effectively required because of our existing feature set. > Regards, > -- > Rowan Collins > [IMSoP]