On Sat, Jul 14, 2018 at 7:09 AM Rowan Collins <rowan.coll...@gmail.com> wrote:
>
> Hi all,
>
> As briefly mentioned, I think the approach to non-nullable types in the typed 
> properties proposal needs more discussion, to make sure we're not repeating 
> Tony Hoare's "billion-dollar mistake".
>
> For parameter hints, nullability is naturally optional, particularly in PHP 
> where "nullable Foo" is equivalent to a union type "null or Foo". For 
> properties, this isn't the case, because every property must have some 
> initial state.
>
> 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 properties 
> 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" illegal, 
> but allow "public ?Foo $foo=null".
>
> The current RFC proposes the next simplest solution, which is to allow 
> non-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 
> object properties to be in, which behaves differently from everything else in 
> the language. There will then be three or four different ways for an object 
> 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 
> implicit 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 = 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 safely 
> call $v->validFrom->getTimestamp(), but need to check for nulls before doing 
> 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 have to be 
> *more* careful, and use isset() or ?? instead.
>
> 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.
>
>
> 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 initialisation 
> of non-nullable properties, using "two-phase initialisation": 
> https://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 read 
> operations, so there is no need for a specific error when accessing 
> uninitialised 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 
> mandatory parent constructor calls, so would need a different way to mark 
> this stage. 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 
> point.
>
> One possibility would be to add a new keyword like "initialize" which must be 
> added to constructors in the presence of non-nullable properties. Above 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 
> properties 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]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to