On Thu, 9 Jan 2020 at 16:31, Nikita Popov <nikita....@gmail.com> wrote:

> On Thu, Jan 9, 2020 at 4:06 PM Rowan Tommins <rowan.coll...@gmail.com>
> wrote:
>
> > On Thu, 9 Jan 2020 at 14:23, Andreas Hennings <andr...@dqxtech.net>
> wrote:
> >
> > > > However, $this is not a real type, and it is unclear what the
> advantage
> > > of specifying $this rather than static would be from a type system
> level
> > > perspective.
> > >
> > > Perhaps not from a "type system level", but from a more broad "enforced
> > > contract" level.
> > > E.g. IDEs or code inspection tools can warn if a method will not return
> > > $this.
> > > This also means recursive calls also need to return $this instead of
> > > static.
> > >
> > > class C {
> > >   function foo(): static {
> > >     return clone $this;
> > >   }
> > >   function bar(): $this {
> > >     return $this->foo();  // IDE can complain.
> > >   }
> > > }
> > >
> >
> >
> > I think there are two different purposes for annotating return types:
> >
> > 1) Contracts that tell the caller what values they should expect when
> > calling the function.
> > 2) Constraints on the implementation which don't affect the caller, but
> > allow the author to catch certain bugs.
> >
> > The primary purpose, in my mind, is (1), with (2) generally coming as a
> > side-effect: if your contract is to return an int, then tools can warn
> you
> > when you don't.
> >
> > All concrete types can be seen this way: scalars, classes, and
> pseudo-types
> > like "iterable" are all contracts that calling code can rely on. "self",
> > "parent", and "static" fit into that list fine, because they're
> ultimately
> > specifying a class name.
> >
> > The special "void" keyword doesn't actually make sense as a contract
> given
> > PHP's calling convention - as far as the calling code's concerned, it's
> > equivalent to "null". So it exists only for purpose (2), constraining the
> > implementation for the benefit of the function's author.
> >
> > $this would fit into the same category - as far as calling code is
> > concerned it is equivalent to "static", unless they're doing something
> very
> > specific with object identity. This makes it an odd constraint on
> > interfaces, for example - DateTimeInterface exists specifically to have
> > mutable and immutable implementations, and a return type of $this would
> > explicitly prevent that.
> >
> > If we add ": $this" alongside ": void", I wonder where that takes us
> next -
> > what other constraints on a function can be expressed using that notation
> > which aren't contracts on the value seen by the caller? If we don't want
> to
> > explore that question, should we avoid adding ": $this"?
> >
>
> An argument could be made that $this does also specify a certain contract
> to the caller: That the API may be used fluently or not without change in
> functionality. That is
>
>     $foo->setBar();
>     $foo->setBaz();
>
> must be strictly equivalent to
>
>     $foo
>        ->setBar()
>        ->setBaz()
>     ;
>
> The same is not the case for a plain "static" type. In fact, I think that
> for all other uses of "static" outside of fluent interfaces, not using the
> return value would be a programming error.
>
> But still, this kind of contract is not a type-system contract, and I'm not
> sure it's a good idea to mix other types of API contracts into the type
> system in this fashion.
>

We currently don't have another "system" where this kind of info could be
specified.
And in this case, $this also implies static, so if we would use whichever
other system to specify $this, the type hint "static" would become
redundant.

"@return $this" is common in phpdoc (*) since a while, and so far I have
not seen any problems with it.

If we ask "where does this lead?", one natural next step might be to
specifically say that the return type is the same type, but NOT $this.
So, a promise that we really get a new object which we can modify without
changing the original object.

I don't know how we would express this. Perhaps ": clone", but this would
be too specific imo, because whether it is a clone is an implementation
detail.

In phpdoc (*) there is no common syntax for "static, but not $this", so
perhaps it was not needed yet.

And in fact, an immutable wither can safely return the original object if
no changes are needed, if other methods are also immutable.

(*) When I say "phpdoc", I really mean the kinds of docs that people
commonly use in the wild, and that are understood by IDEs.
Which of that is documented and supported by the phpdoc library is a
different question.



>
> Regards,
> Nikita
>

Reply via email to