[PSR-7] Opinions requested on potential patch

203 views
Skip to first unread message

Matthew Weier O'Phinney

unread,
Aug 3, 2016, 2:54:13 PM8/3/16
to php...@googlegroups.com
Hi!

I've been reviewing pull requests against the http-message repository, and had
given my thumbs-up to the following:

- https://github.com/php-fig/http-message/pull/50

That pull request update all `@return self` annotations to `@return static`. To
summarize the discussion, `@return static` is interpreted by both phpDoc and
most popular IDEs in such a way as to resolve to the class in which invocation
occurs, vs `@return self`, which resolves to the class in which it was defined.
Essentially, `@return self` is problematic when used in interfaces with
inheritance (such as `RequestInterface` inheriting from `MessageInterface`, or
`ServerRequestInterface` inheriting from `RequestInterface`, as the return value
might be of a looser type.

Additionally, `@return static` has a *connotation* that a new instance, not the
same instance, is being returned, which is the specific semantic we already
define within the PSR-7 interfaces.

However, Michael Cullum posed the following question: is such a change
considered a *fix* (because it updates the syntax to match intent) or a
*clarification* (which would require a vote)?

Opinions?

--
Matthew Weier O'Phinney
mweiero...@gmail.com
https://mwop.net/

Woody Gilk

unread,
Aug 3, 2016, 2:56:18 PM8/3/16
to PHP Framework Interoperability Group
I've always considered the `@return self` to be a bug in the PSR-7 and
as such would be a *fix*.
--
Woody Gilk
http://about.me/shadowhand
> --
> You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/CAJp_myVMXBh24D5u6C54CuFUqqtymStcW6rW3MopTrJ7U0fcFw%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

Colin O'Dell

unread,
Aug 3, 2016, 3:00:35 PM8/3/16
to PHP Framework Interoperability Group

Woody Gilk

unread,
Aug 3, 2016, 3:03:12 PM8/3/16
to PHP Framework Interoperability Group

Colin, because it doesn't.



For more options, visit https://groups.google.com/d/optout.
--

Colin O'Dell

unread,
Aug 3, 2016, 3:05:09 PM8/3/16
to PHP Framework Interoperability Group
Right, I wasn't thinking clearly.  Please disregard! :)

Paul Jones

unread,
Aug 3, 2016, 3:11:01 PM8/3/16
to php...@googlegroups.com

> On Aug 3, 2016, at 13:54, Matthew Weier O'Phinney <mweiero...@gmail.com> wrote:
>
> is such a change
> considered a *fix* (because it updates the syntax to match intent) or a
> *clarification* (which would require a vote)?

IMO that's a fix; no vote needed.


--

Paul M. Jones
http://paul-m-jones.com



guilher...@gmail.com

unread,
Aug 3, 2016, 3:26:26 PM8/3/16
to php...@googlegroups.com
Hi Matthew,

In this specific case (when considering an interface), @return self is wrong, as there is no way to return purely an interface instance. You just can't instantiate an interface.

However, we should never assume that @return self is wrong in all scenarios, and IDEs should make sure that overriding it is not wrong. Conceptually, I can have a @return static in an interface, but the implementation overrides it to be @return self. This is needed in the case we're doing something like this:

interface Factory {
    /** 
     *@return static 
     */
    function create();
}

class BarFactory implements Factory {
    /** 
     *@return self 
     */
    public function create() { 
        return new self(); // Yes, create the Factory as an instance for demonstration purposes... =)
    }
}

Cheers,

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Guilherme Blanco
Lead Architect at E-Block

Alexander Makarov

unread,
Aug 4, 2016, 6:20:21 AM8/4/16
to PHP Framework Interoperability Group
Looks like a fix to me.

Krzysiek Piasecki

unread,
Aug 4, 2016, 6:44:25 AM8/4/16
to PHP Framework Interoperability Group
In my opinion both 'self' and 'static' are for the implementors. These interfaces should be describe as always returning concrete interface.
 

-- 
Krzysiek Piasecki

Théo FIDRY

unread,
Aug 5, 2016, 7:46:08 PM8/5/16
to PHP Framework Interoperability Group
>Additionally, `@return static` has a *connotation* that a new instance, not the 
same instance, is being returned, which is the specific semantic we already 
define within the PSR-7 interfaces. 

From PSR-5:

>`self`, the element to which this type applies is of the same class as which the documented element is originally contained.
>`static`, the element to which this type applies is of the same class as which the documented element is contained, or when encountered in a subclass is of type of that subclass instead of the original class. This keyword behaves the same way as the keyword for late static binding (not the static method, property, nor variable modifier) as defined by PHP.

So not sure if this connotation is correct. At least from what is said in PSR-5, nothing is said about the return value being the same or a new instance. That said if it was the same instance, `$this` would be more appropriate right?

>In this specific case (when considering an interface), @return self is wrong, as there is no way to return purely an interface instance. You just can't instantiate an interface.
>However, we should never assume that @return self is wrong in all scenarios, and IDEs should make sure that overriding it is not wrong. Conceptually, I can have a @return static in an interface, but the implementation overrides it to be @return self. This is needed in the case we're doing something like this:

if you have

interface DummyInterface {
  /** @return self */
  public function create();
}

class Foo implements DummyInterface {
  public function create();
}

It would just mean that `Foo::create()` may return another implementation of `DummyInterface` than `Foo`, which is perfectly correct. However, if you specified `@return static` in `DummyInterface::create()`, then this case would become incorrect: you are forcing `Foo::create()` to return a `Foo` instance.

Well, PSR-5 is not finished, but that's still a reference.

Ciaran McNulty

unread,
Aug 6, 2016, 3:16:12 PM8/6/16
to PHP Framework Interoperability Group

On Wednesday, 3 August 2016 19:54:13 UTC+1, Matthew Weier O'Phinney wrote:
That pull request update all `@return self` annotations to `@return static`. To
summarize the discussion, `@return static` is interpreted by both phpDoc and
most popular IDEs in such a way as to resolve to the class in which invocation
occurs, vs `@return self`, which resolves to the class in which it was defined.

Is it a requirement that an instance of the same concreted is returned, or is anything implementing the interface acceptable?
 
Essentially, `@return self` is problematic when used in interfaces with
inheritance (such as `RequestInterface` inheriting from `MessageInterface`, or
`ServerRequestInterface` inheriting from `RequestInterface`, as the return value
might be of a looser type.

I don't understand this argument. Returning a subtype fits the return contract, doesn't it?

-C

Matthew Weier O'Phinney

unread,
Aug 9, 2016, 10:53:54 AM8/9/16
to php...@googlegroups.com
On Sat, Aug 6, 2016 at 2:16 PM, Ciaran McNulty <ma...@ciaranmcnulty.com> wrote:
>
> On Wednesday, 3 August 2016 19:54:13 UTC+1, Matthew Weier O'Phinney wrote:
>>
>> That pull request update all `@return self` annotations to `@return
>> static`. To
>> summarize the discussion, `@return static` is interpreted by both phpDoc
>> and
>> most popular IDEs in such a way as to resolve to the class in which
>> invocation
>> occurs, vs `@return self`, which resolves to the class in which it was
>> defined.
>
> Is it a requirement that an instance of the same concreted is returned, or
> is anything implementing the interface acceptable?

The idea with PSR-7 is that a new instance of the same type is
returned. So, in the case of ServerRequestInterface::withHeader(), you
would expect another ServerRequestInterface instance be returned.
withHeader(), however, is defined as part of MessageInterface (and
ServerRequestInterface inherits from that).

>> Essentially, `@return self` is problematic when used in interfaces with
>> inheritance (such as `RequestInterface` inheriting from
>> `MessageInterface`, or
>> `ServerRequestInterface` inheriting from `RequestInterface`, as the return
>> value
>> might be of a looser type.
>
>
> I don't understand this argument. Returning a subtype fits the return
> contract, doesn't it?

See above. I'd expect ServerRequestInterface::withHeader() to return a
ServerRequestInterface instance, and not just *any* MessageInterface.
Since MessageInterface defines withHeader(), using `@return self`
there implies any MessageInterface implementation may be returned —
which means that a `ResponseInterface` return value would be valid! We
want to limit to the more specific subtype — in this case, the
ServerRequestInterface.

`@return static` properly denotes that we should resolve to the subtype.
Reply all
Reply to author
Forward
0 new messages