Re: [PHP-DEV] [VOTE] Nullable intersection types

2021-08-14 Thread Alexandru Pătrănescu
On Sun, Aug 15, 2021, 04:33 Marco Pivetta  wrote:

> Heyo, just a follow-up.
>
> On Fri, 13 Aug 2021, 13:30 Marco Pivetta,  wrote:
>
> > Hey Nicolas,
> >
> > I voted NO on this one. I'm not opposed to nullable intersection types,
> > but not in PHP 8.1.
> >
> > Specifically, I'm waiting for the first RC releases to land in September
> > to even start looking at PHP 8.1 support for any of my projects, and
> > stability is key.
> >
> > I also am not on board with the lack of design around reflection API
> here.
> >
>
> I just re-checked the RFC, and I'm completely against the reflection design
> in here (which I previously dismissed as "oversight").
>
> An `(A&B)|null` is **not** a `ReflectionIntersectionType`, but should
> instead be a `ReflectionUnionType`.
>
>
> Therefore, adding this to the "NO" reasons, since we'll otherwise have to
> live with this mistake for many years to come.
>
>
Just to mention here, `A|null` is also not a `ReflectionUnionType` but a
`ReflectionNamedType`,
union with null already being a special case.
https://3v4l.org/lM9NJ

But the fact that these things might not be known clearly and the fact that
nullability concept wasn't discussed and agreed on for the type system in
general, I also think the feature can wait for 8.2.

Alex


Re: [PHP-DEV] [VOTE] Nullable intersection types

2021-08-14 Thread Marco Pivetta
Heyo, just a follow-up.

On Fri, 13 Aug 2021, 13:30 Marco Pivetta,  wrote:

> Hey Nicolas,
>
>
> On Fri, Aug 13, 2021 at 11:35 AM Nicolas Grekas 
> wrote:
>
>> Hi everyone,
>>
>> I'm happy to announce that the vote for nullable intersection types is now
>> open:
>> https://wiki.php.net/rfc/nullable_intersection_types
>>
>> It'll close in two weeks, on the 27th.
>>
>
> I voted NO on this one. I'm not opposed to nullable intersection types,
> but not in PHP 8.1.
>
> Specifically, I'm waiting for the first RC releases to land in September
> to even start looking at PHP 8.1 support for any of my projects, and
> stability is key.
>
> I also am not on board with the lack of design around reflection API here.
>

I just re-checked the RFC, and I'm completely against the reflection design
in here (which I previously dismissed as "oversight").

An `(A&B)|null` is **not** a `ReflectionIntersectionType`, but should
instead be a `ReflectionUnionType`.


Therefore, adding this to the "NO" reasons, since we'll otherwise have to
live with this mistake for many years to come.

>


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Mike Schinkel
> On Aug 14, 2021, at 10:40 AM, Jordan LeDoux  wrote:
> 
> Never is treated as the bottom type for the purpose of Liskov substitution
> already with its use as a return type. The exception to this in its use as
> a return type is that it isn't treated as the union identity in the return
> type. However, for LSP never is the bottom type when it comes to return
> values. It would, in my mind, be highly inconsistent to have a different
> bottom type for return values than for arguments, so personally I am very
> against using a term other than never. As mentioned in the doc, I wasn't
> able to find a single existing language that has multiple bottom types. If
> anyone is able to provide an example of this, I would appreciate it.

Reading through all the replies on this topic it seems that the functionality 
for the proposal is less controversial than the keyword chosen to identify it.  

It occurs to me that while `never` is the correct keyword for the bottom type 
given past decisions, maybe choosing to use a bottom type to provide this 
functionality is not an idea choice?

If we approach this use-case requirements from a perspective of "this keyword 
indicates that you must implement in a child" then I think we already have a 
keyword that has appropriate semantics compared with the confusing semantics of 
`never` used for a parameter: `abstract`.

So then instead of `never` we could choose the following:

 interface CollectionInterface
 {
 public function add(abstract $input): self;
 }

`abstract` could also work for return types and property types:

 interface Foo
{
 public abstract $bar;
 public function baz(): abstract {}
}

Or am I missing something?  Is there a reason `abstract` would not be a better 
choice than `never`?



That said, I do have a rhetorical question to ask, to be pondered by those who 
are better attuned to the ramifications of allowing interfaces to become less 
strict than they already are.

From my career-long understanding of declared interfaces the primary (only?) 
reason to use them is to signal and enforce a guarantee that a specific set of 
signatures are available in an instance of a class that implements the 
interface. But if an interface can be defined as something that can can easily 
change based on the implementor, the guarantee that we could previously depend 
on its signatures will no longer be, well, guaranteed.

My gut feeling tells me that will be a bad direction for us to take with PHP.  
What do other's think?



After writing the above it occurred to me the solution to the above problem 
already conceptually exists, too, classes get to use the `abstract` keyword 
when their children need to be required to implement something.

If PHP requires interfaces with parameters defined as type `abstract` (or 
`never` if we must)  then those interfaces should also be required to be 
declared `abstract`:

 abstract interface CollectionInterface
 {
 public function add(abstract $input): self;
 }
 Class IntCollection implements CollectionInterface 
 {
 public function add(int $input): self;
 }

The primary tangible difference between abstract and concrete interfaces would 
be in documentation, reflection, and possible an is_abstract() function so that 
code that needs to ensure an exact specific interface could do so.

The benefit of this approach as it appears to me is that (concrete) interfaces 
can retain their same level of guarantee where abstract interfaces would not be 
required to maintain such a guarantee.  #jmtcw

Thoughts?

-Mike

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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Jordan LeDoux
On Sat, Aug 14, 2021 at 10:12 AM Claude Pache 
wrote:

>
> If users of that interface would suddenly be *required* to specify a
> parameter type, whereas previously they were *forbidden* to specify one,
> except a meaningless `mixed`... it would be not nice and useless.
>
> Moreover, note that `mixed` was only introduced very recently, in 8.0: so
> that, it would be impossible to implement `ArrayAccess` on code that work
> both in 7.x and a future version with the updated interface. Not only would
> it be not nice, but it would be positively harmful.
>
>
Those are some excellent points I hadn't considered. I will remove the
explicit widening from this RFC and update my pull request. I was
considering having that aspect as a separate vote, but this point about
mixed being a recent addition was a point I hadn't considered, and to me
suggests that it shouldn't even be an option in the RFC, particularly
because we would like to update the ArrayAccess interface and that will
affect a lot of existing code.

Jordan


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Claude Pache



> 
> On Fri, 13 Aug 2021 at 19:27, Jordan LeDoux  wrote:
> 
>> Hey internals,
>> 
>> I've been working on the draft for my operator overloading RFC, and in
>> doing so I encountered a separate change that I would like to see.
>> 
>> That is, the use of `never` as an argument type for interfaces. Since
>> arguments in PHP are contravariant to preserve Liskov substitution, `never`
>> as the bottom type should indicate that implementing classes can require
>> any type combination they want. This is in fact consistent with type theory
>> and set theory, and is how the bottom type is treated in several other
>> languages.
>> 
>> In this case, the bottom type would be used to indicate covariant parameter
>> polymorphism while not conflicting with LSP.
>> 
>> This would provide a sort of minimal form of generics to PHP without the
>> issues that actual generics present from an implementation perspective. It
>> would not, however, restrict or hinder any future RFC for generics.
>> 
>> This is at the first draft stage, and I currently have the RFC on a github
>> repo to allow for easy contribution and collaboration.
>> 
>> Any feedback is greatly appreciated.
>> 
>> https://github.com/JordanRL/never-argument-type
>> 
>> Jordan
>> 


> Le 14 août 2021 à 18:19, Matthew Brown  a écrit :
> 
> Hey!
> 
> Using the "never" type to require that downstream libs specify a type does
> not make intuitive sense to me, because the same is not true the other way
> (covariantly) for return types.
> 
> The existence of a "never" type on an overriding method does not require
> that upstream libs specify a return type — this is perfectly valid:
> 
> class A {
>  public function foo() {}
> }
> class AChild extends A {
>  public function foo():never { exit; }
> }
> 
> Best wishes,
> 
> Matt


Indeed, I was going to write something similar. Concretely, I assume that one 
would want to update the ArrayAccess internal interface as follows:

```php
interface ArrayAccess {
public function offsetGet(never $x): mixed;
// ...
}
```
If users of that interface would suddenly be *required* to specify a parameter 
type, whereas previously they were *forbidden* to specify one, except a 
meaningless `mixed`... it would be not nice and useless.

Moreover, note that `mixed` was only introduced very recently, in 8.0: so that, 
it would be impossible to implement `ArrayAccess` on code that work both in 7.x 
and a future version with the updated interface. Not only would it be not nice, 
but it would be positively harmful.


—Claude

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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Matthew Brown
Hey!

Using the "never" type to require that downstream libs specify a type does
not make intuitive sense to me, because the same is not true the other way
(covariantly) for return types.

The existence of a "never" type on an overriding method does not require
that upstream libs specify a return type — this is perfectly valid:

class A {
  public function foo() {}
}
class AChild extends A {
  public function foo():never { exit; }
}

Best wishes,

Matt

On Fri, 13 Aug 2021 at 19:27, Jordan LeDoux  wrote:

> Hey internals,
>
> I've been working on the draft for my operator overloading RFC, and in
> doing so I encountered a separate change that I would like to see.
>
> That is, the use of `never` as an argument type for interfaces. Since
> arguments in PHP are contravariant to preserve Liskov substitution, `never`
> as the bottom type should indicate that implementing classes can require
> any type combination they want. This is in fact consistent with type theory
> and set theory, and is how the bottom type is treated in several other
> languages.
>
> In this case, the bottom type would be used to indicate covariant parameter
> polymorphism while not conflicting with LSP.
>
> This would provide a sort of minimal form of generics to PHP without the
> issues that actual generics present from an implementation perspective. It
> would not, however, restrict or hinder any future RFC for generics.
>
> This is at the first draft stage, and I currently have the RFC on a github
> repo to allow for easy contribution and collaboration.
>
> Any feedback is greatly appreciated.
>
> https://github.com/JordanRL/never-argument-type
>
> Jordan
>


Re: [PHP-DEV] Unwrap reference after foreach

2021-08-14 Thread Claude Pache

> Le 13 août 2021 à 15:28, Nikita Popov  a écrit :
> 
> Hi internals,
> 
> I'd like to address a common footgun when using foreach by reference:
> https://wiki.php.net/rfc/foreach_unwrap_ref
> 
> This addresses the issue described in the big red box at
> https://www.php.net/manual/en/control-structures.foreach.php. While this is
> "not a bug" (as our bug tracker can regularly attest), it's rather
> unexpected, and we could easily avoid it...
> 
> Regards,
> Nikita

A case that should be mentioned in the RFC is destructuring:

```php
foreach ($foo as [ $x, &$y ]) { /*  */ }
```
https://3v4l.org/A5Vi7 

I assume that the reference in `$y` would be unwrapped after the loop?

—Claude

Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Jordan LeDoux
The RFC has been moved to the wiki:
https://wiki.php.net/rfc/never_for_parameter_types

The most critical points of discussion in my mind are:

1. Should never require **explicit** widening as discussed? This could be
very useful but would make it the only case in PHP where omitting a type is
not seen as "mixed". (This could be set up as a secondary vote.)
2. If the answer to question #1 is yes, should an error specific to this
case be provided instead of the more generic "declaration of A must be
compatible with B"?
3. Should we attempt to limit usage of this feature to only interfaces and
abstract classes? (NOTE: It's unclear how such a thing would be implemented
or if it is feasible.) If it must be available to all function parameters
due to implementation, is that acceptable?

To clarify, this feature is most critically useful for certain internally
provided interfaces, such as ArrayAccess or the proposed interfaces in my
draft of Operator Overloads. I'm sure it would find use in user code as
well (I know that I would use it in certain interfaces in my own
libraries), but it's absence actually makes certain core features very
difficult to provide in an intelligent way.

Jordan


Re: [PHP-DEV] Unwrap reference after foreach

2021-08-14 Thread Hans Henrik Bergan
well today you can do
foreach($it as &$value){...} unset($value);
- which is pretty close, but it will break with
$value="initial";foreach($it as &$value){...}unset($value); echo $value;
here $value will not be "initial", it will be undefined, however you *CAN*
do

$value="initial";(function()use(&$it){foreach($it as
&$value){...}unset($value);})(); echo $value;

and it will still contain "initial" and here the unset is even unnecessary,
but yeah..
 usually people do not go to such lengths to get a contained variable scope
^^


On Sat, 14 Aug 2021 at 15:23, Hossein Baghayi 
wrote:

> On Fri, 13 Aug 2021 at 17:59, Nikita Popov  wrote:
>
> > I'd like to address a common footgun when using foreach by reference:
> > https://wiki.php.net/rfc/foreach_unwrap_ref
> >
>
> Hello,
> I had a question regarding this.
> Wouldn't it be possible to limit ```$value```'s scope to only foreach's
> block then discard it? Unless it was already defined elsewhere.
>
> ```
> foreach($nice_stuff as &$value) {} //we are done here and no need to keep
> value around.
>
> echo $value; // $value is Undefined here.
>
> $value = null;
> foreach($stuff as &$value) {} //we can keep the value here since it doesn't
> belong to foreach.
>
> echo $value; // prints some fancy pancy stuff
> ```
>


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Jordan LeDoux
On Sat, Aug 14, 2021 at 7:01 AM AllenJB  wrote:

>
> Whilst I understand there's a historical aspect to the keyword naming
> used in this RFC, as a PHP developer, I think the use of "never" here is
> going to be confusing to people when considered along-side the never
> return type.
>
> I think it would make more sense to change the keyword for this RFC to
> something else such as "any", "unspecified", "unknown" or "specify".
> (Whilst "nothing" might also be considered given its use in other
> languages, I don't think the meaning / purpose is that clear).
>
> This RFC only considers this feature for arguments. Why is it also not a
> valid feature for return types? I think it might be useful for abstract
> classes and interfaces (for example, the Iterator interface) to force
> implementers to specify a return type for certain methods whilst not
> specifying anything about it themselves.
>
>
Never is treated as the bottom type for the purpose of Liskov substitution
already with its use as a return type. The exception to this in its use as
a return type is that it isn't treated as the union identity in the return
type. However, for LSP never is the bottom type when it comes to return
values. It would, in my mind, be highly inconsistent to have a different
bottom type for return values than for arguments, so personally I am very
against using a term other than never. As mentioned in the doc, I wasn't
able to find a single existing language that has multiple bottom types. If
anyone is able to provide an example of this, I would appreciate it.

Never is the most common bottom type in other languages from the brief
survey I did before putting this RFC together, with "nothing" as the second
most common.

Return types are covariant with inheritance, not contravariant. The return
type equivalent from an inheritance perspective would be "mixed", as it is
the top type and is a supertype of any type in PHP, allowing inheriting
classes to narrow the type in any way they wish. The main difference is
that mixed is a valid type at runtime for values, since it contains all
valid values. Meanwhile, never contains no valid values, thus forcing type
expansion upon inheritance. I can see your point about how it might be
useful for interfaces to require an explicit return type of their
implementers, but that is a bit more complicated of a change (and a more
breaking one), and the point of this RFC isn't really to reorganize the
entire type system.

To retain Liskov substitution, the type to mirror this behavior for return
values would be mixed since that's the top type, and changing mixed so that
it required an explicit type of all inheriting classes would break quite a
bit of code. This RFC as it is written has no BC breaks.

Jordan


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread G. P. B.
On Sat, 14 Aug 2021 at 16:01, AllenJB  wrote:

> This RFC only considers this feature for arguments. Why is it also not a
> valid feature for return types? I think it might be useful for abstract
> classes and interfaces (for example, the Iterator interface) to force
> implementers to specify a return type for certain methods whilst not
> specifying anything about it themselves.
>

You can already do this since PHP 7.4, because return types are co-variant.
Any implementor can add a return type to specify what they return, as mixed
is the top type.
This RFC is not about "forcing" X to declare a type, it is to allow
variance changes which cannot currently be done
(well except adding a dummy argument type of bool that you can widen to
something more general and just need to check the case is not bool but
that's also hackery).

This feature is for sure an edge case and not a replacement for generics,
but the main motivation I see is to be useful for engine hooks like a
Equatable/Ordable comparison overload or more general operator overloading,
where if the object doesn't specify it's capability it is like it
"implements" the magic method (or whatever it comes to be) with an argument
type of "never" which results in a TypeError meaning it does not support
this operation.

Maybe it does not make sense to make this available for userland, but I do
think it is somewhat necessary for these sorts of features to have this
concept.

Best regards,

George P. Banyard


Re: [PHP-DEV] Unwrap reference after foreach

2021-08-14 Thread Hans Henrik Bergan
Speaking of, i hope that one day we can support javascript-style let in php
:) like
foreach($it as let &$v){}
but that's a discussion for another thread (and i'm sure it has been
discussed before, i haven't actually checked though)

On Sat, 14 Aug 2021 at 15:23, Hossein Baghayi 
wrote:

> On Fri, 13 Aug 2021 at 17:59, Nikita Popov  wrote:
>
> > I'd like to address a common footgun when using foreach by reference:
> > https://wiki.php.net/rfc/foreach_unwrap_ref
> >
>
> Hello,
> I had a question regarding this.
> Wouldn't it be possible to limit ```$value```'s scope to only foreach's
> block then discard it? Unless it was already defined elsewhere.
>
> ```
> foreach($nice_stuff as &$value) {} //we are done here and no need to keep
> value around.
>
> echo $value; // $value is Undefined here.
>
> $value = null;
> foreach($stuff as &$value) {} //we can keep the value here since it doesn't
> belong to foreach.
>
> echo $value; // prints some fancy pancy stuff
> ```
>


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread AllenJB



On 14/08/2021 00:27, Jordan LeDoux wrote:

Hey internals,

I've been working on the draft for my operator overloading RFC, and in
doing so I encountered a separate change that I would like to see.

That is, the use of `never` as an argument type for interfaces. Since
arguments in PHP are contravariant to preserve Liskov substitution, `never`
as the bottom type should indicate that implementing classes can require
any type combination they want. This is in fact consistent with type theory
and set theory, and is how the bottom type is treated in several other
languages.

In this case, the bottom type would be used to indicate covariant parameter
polymorphism while not conflicting with LSP.

This would provide a sort of minimal form of generics to PHP without the
issues that actual generics present from an implementation perspective. It
would not, however, restrict or hinder any future RFC for generics.

This is at the first draft stage, and I currently have the RFC on a github
repo to allow for easy contribution and collaboration.

Any feedback is greatly appreciated.

https://github.com/JordanRL/never-argument-type

Jordan


Whilst I understand there's a historical aspect to the keyword naming 
used in this RFC, as a PHP developer, I think the use of "never" here is 
going to be confusing to people when considered along-side the never 
return type.


I think it would make more sense to change the keyword for this RFC to 
something else such as "any", "unspecified", "unknown" or "specify". 
(Whilst "nothing" might also be considered given its use in other 
languages, I don't think the meaning / purpose is that clear).


This RFC only considers this feature for arguments. Why is it also not a 
valid feature for return types? I think it might be useful for abstract 
classes and interfaces (for example, the Iterator interface) to force 
implementers to specify a return type for certain methods whilst not 
specifying anything about it themselves.


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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Jordan LeDoux
On Sat, Aug 14, 2021 at 6:25 AM Nikita Popov  wrote:

>
> function addMultiple(CollectionInterface $collection, mixed ...$inputs):
> void {
> foreach ($inputs as $input) $collection->add($input);
> }
>
> A static analyzer should flag this CollectionInterface::add() call as
> invalid, because mixed is passed to never. Effectively, this means that an
> interface using never argument types cannot actually be used in anything
> *but* inheritance -- so what is its purpose?
>
>
When used as a sort of... pseudo-generics replacement, you'd need to use
Docblocks to specify these, because **this feature is not generics** (which
you correctly pointed out). I probably should have made that MORE clear so
as to not confuse or trick anyone.

If this RFC were passed, it could be sort of used like generics but it
would be a bit hacky to use it that way as your example illustrates. In the
absence of generics, this would probably be used as a stopgap in
combination with docblocks. That's the point I was trying to make. :)

The main value I see from an inheritance perspective is using never to
disallow an omitted type. The inheriting class may specify *any* type, even
mixed, but it must do so explicitly.

Larry:
> So... if I am following correctly, the idea is to allow `never` to be
used in an interface/abstract method only, as a way to indicate "you must
specify a type here of some kind; I don't care what, even mixed, but you
have to put something".  Am I following?

This is essentially correct, yes, however it's important to note, and I
don't want to mislead anyone here: it's not possible (to my knowledge) to
*only* allow this type for parameters on interfaces and abstracts. Or at
least, doing so is much, much more complicated. The patch I provided is
about 5 lines different, however it allows never as a parameter type
everywhere, including functions.

This is, to my mind, acceptable because never will behave entirely
consistently with a bottom type in all such scenarios. It will compile just
fine, but if you call any function that has an argument type of never, you
will get TypeError. No type which can be provided at runtime, even null,
will satisfy the type never, so practically it makes a function uncallable
when used as an argument type. It must be widened through inheritance to be
used.

Jordan


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Nikita Popov
On Sat, Aug 14, 2021 at 1:27 AM Jordan LeDoux 
wrote:

> Hey internals,
>
> I've been working on the draft for my operator overloading RFC, and in
> doing so I encountered a separate change that I would like to see.
>
> That is, the use of `never` as an argument type for interfaces. Since
> arguments in PHP are contravariant to preserve Liskov substitution, `never`
> as the bottom type should indicate that implementing classes can require
> any type combination they want. This is in fact consistent with type theory
> and set theory, and is how the bottom type is treated in several other
> languages.
>
> In this case, the bottom type would be used to indicate covariant parameter
> polymorphism while not conflicting with LSP.
>
> This would provide a sort of minimal form of generics to PHP without the
> issues that actual generics present from an implementation perspective. It
> would not, however, restrict or hinder any future RFC for generics.
>
> This is at the first draft stage, and I currently have the RFC on a github
> repo to allow for easy contribution and collaboration.
>
> Any feedback is greatly appreciated.
>
> https://github.com/JordanRL/never-argument-type
>

There's two sides to this coin: While using a never argument type allows
you to avoid the LSP problem, it also means that you cannot call the method
while typing against the interface. Let's take your CollectionInterface

interface CollectionInterface {
public function add(never $input): self;
}

and actually try to make use of it:

function addMultiple(CollectionInterface $collection, mixed ...$inputs):
void {
foreach ($inputs as $input) $collection->add($input);
}

A static analyzer should flag this CollectionInterface::add() call as
invalid, because mixed is passed to never. Effectively, this means that an
interface using never argument types cannot actually be used in anything
*but* inheritance -- so what is its purpose?

Compare this to generics. The interface changes to

interface CollectionInterface {
public function add(T $input): self;
}

and the use changes to

function addMultiple(CollectionInterface $collection, T ...$inputs):
void {
foreach ($inputs as $input) $collection->add($input);
}

Now a T argument is passed to a T parameter, and everything is fine.

Regards,
Nikita


Re: [PHP-DEV] Unwrap reference after foreach

2021-08-14 Thread Hossein Baghayi
On Fri, 13 Aug 2021 at 17:59, Nikita Popov  wrote:

> I'd like to address a common footgun when using foreach by reference:
> https://wiki.php.net/rfc/foreach_unwrap_ref
>

Hello,
I had a question regarding this.
Wouldn't it be possible to limit ```$value```'s scope to only foreach's
block then discard it? Unless it was already defined elsewhere.

```
foreach($nice_stuff as &$value) {} //we are done here and no need to keep
value around.

echo $value; // $value is Undefined here.

$value = null;
foreach($stuff as &$value) {} //we can keep the value here since it doesn't
belong to foreach.

echo $value; // prints some fancy pancy stuff
```


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Deleu
On Sat, Aug 14, 2021, 14:48 G. P. B.  wrote:

> On Sat, 14 Aug 2021 at 10:55, Deleu  wrote:
>
>> Hi Jordan,
>>
>> Does it make sense to explain in the RFC the difference between never and
>> mixed in this context? The RFC vaguely mentions that never can never be
>> used directly, but if it's limited to abstract class and interfaces, isn't
>> that already impossible to use directly? Or does it mean that the type
>> would "be allowed" on any function, but because of its intrinsic behavior
>> it would always fail if used in non-abstract methods?
>>
>> Another clarification I'd be interested is about dropping the type
>> declaration entirely (e.g. https://3v4l.org/a4bfs), because of covariance
>> (or contravariance, I never know), sub classes can completely drop type
>> declaration entirely. Will never not allow this? Why? Why not? If it does
>> allow this, does it really differ from not having any type declaration on
>> the abstract function?
>>
>> My knowledge in this area is practically null so if I'm asking stupid
>> questions that are easily explained by some blog post I'd he happy to read
>> it.
>>
>
> never and mixed are on opposite sides of the type hierarchy.
> mixed is the top type, meaning it's the supertype of any other types, and
> any other type is a subtype of mixed (excluding void which is not really a
> "type" if you look at it, from my understanding, in a type theory way).
> never on the other side is the bottom type, meaning it's the subtype of
> any other type, and any other type is a supertype of never.
> Finally a lack of type declaration is treated as mixed.
>
> Liskov's substitutions rules dictate that return types are co-variant i.e.
> more specific, and argument types are contra-variant i.e. more general.
> This is why any return type can be replaced by never and any argument type
> can have it's type dropped/changed to mixed.
> As such replacing never by mixed in an argument is totally possible as
> mixed is a wider type than never.
>

This was incredibly useful, thank you very much. The essence that I took
away is that if I declare mixed on my interface, then making it more
specific (co-variant) is impossible e.g.

```
interface A {
public function t(mixed $t);
}


interface B extends A {
public function t(A $t);
}
```

This is where never, being a bottom type, shines.

I guess the bike shed of this one is the awkwardness of declaring an input
as `never` but I'd imagine we'll either get used to it or use a possible
future type alias to do `type something = never`. I guess the best aliases
would be any or something, but given the interesting use case I don't think
it's worth to reject this RFC solely based on how awkward `never $var` is.

TL;DR thank you and I like it.

>


Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Larry Garfield
On Sat, Aug 14, 2021, at 7:48 AM, G. P. B. wrote:
> On Sat, 14 Aug 2021 at 10:55, Deleu  wrote:
> 
> > Hi Jordan,
> >
> > Does it make sense to explain in the RFC the difference between never and
> > mixed in this context? The RFC vaguely mentions that never can never be
> > used directly, but if it's limited to abstract class and interfaces, isn't
> > that already impossible to use directly? Or does it mean that the type
> > would "be allowed" on any function, but because of its intrinsic behavior
> > it would always fail if used in non-abstract methods?
> >
> > Another clarification I'd be interested is about dropping the type
> > declaration entirely (e.g. https://3v4l.org/a4bfs), because of covariance
> > (or contravariance, I never know), sub classes can completely drop type
> > declaration entirely. Will never not allow this? Why? Why not? If it does
> > allow this, does it really differ from not having any type declaration on
> > the abstract function?
> >
> > My knowledge in this area is practically null so if I'm asking stupid
> > questions that are easily explained by some blog post I'd he happy to read
> > it.
> >
> 
> never and mixed are on opposite sides of the type hierarchy.
> mixed is the top type, meaning it's the supertype of any other types, and
> any other type is a subtype of mixed (excluding void which is not really a
> "type" if you look at it, from my understanding, in a type theory way).
> never on the other side is the bottom type, meaning it's the subtype of any
> other type, and any other type is a supertype of never.
> Finally a lack of type declaration is treated as mixed.
> 
> Liskov's substitutions rules dictate that return types are co-variant i.e.
> more specific, and argument types are contra-variant i.e. more general.
> This is why any return type can be replaced by never and any argument type
> can have it's type dropped/changed to mixed.
> As such replacing never by mixed in an argument is totally possible as
> mixed is a wider type than never.
> 
> How I personally see never as an argument type is that you require a
> mandatory argument but you leave the type constraint up to the
> implementation.
> 
> A recent example which bit us in php-src/the PHP documentation is the
> interface of ArrayAccess, all of the $offset parameters have a mixed type.
> Until recently the ArrayObject/ArrayIterator had incorrect stubs [1] by
> indicating that the argument was of type int|string, which practically is
> the case as SPL's ArrayAccess handler will throw a TypeError on different
> types, however this is done manually within the call and not when the call
> is made.
> Ideally the $offset parameter would be of type never such that SPL, and
> userland, can specify what type of offsets they accept, be that the usual
> int|string, only int for list-like objects, only string for dictionary-like
> objects, maybe even object|int|string to allow GMP objects for arbitrary
> precision.
> Whereas every implementer of ArrayAccess is forced to accept mixed for the
> $offset and need to manually enforce the type.
> 
> This is the "power" of the never type as an argument type.
> 
> Best regards,
> 
> George P. Banyard
> 
> [1]
> https://github.com/php/php-src/pull/7215/files#diff-e330df347cac9e68d2d07a06535c534cd8c2438a1af703cd4245b8ce91ec65afL9-R10

So... if I am following correctly, the idea is to allow `never` to be used in 
an interface/abstract method only, as a way to indicate "you must specify a 
type here of some kind; I don't care what, even mixed, but you have to put 
something".  Am I following?

I'm not sure on the type theory of it, but it does feel like a hack at first 
blush.

--Larry Garfield

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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread G. P. B.
On Sat, 14 Aug 2021 at 10:55, Deleu  wrote:

> Hi Jordan,
>
> Does it make sense to explain in the RFC the difference between never and
> mixed in this context? The RFC vaguely mentions that never can never be
> used directly, but if it's limited to abstract class and interfaces, isn't
> that already impossible to use directly? Or does it mean that the type
> would "be allowed" on any function, but because of its intrinsic behavior
> it would always fail if used in non-abstract methods?
>
> Another clarification I'd be interested is about dropping the type
> declaration entirely (e.g. https://3v4l.org/a4bfs), because of covariance
> (or contravariance, I never know), sub classes can completely drop type
> declaration entirely. Will never not allow this? Why? Why not? If it does
> allow this, does it really differ from not having any type declaration on
> the abstract function?
>
> My knowledge in this area is practically null so if I'm asking stupid
> questions that are easily explained by some blog post I'd he happy to read
> it.
>

never and mixed are on opposite sides of the type hierarchy.
mixed is the top type, meaning it's the supertype of any other types, and
any other type is a subtype of mixed (excluding void which is not really a
"type" if you look at it, from my understanding, in a type theory way).
never on the other side is the bottom type, meaning it's the subtype of any
other type, and any other type is a supertype of never.
Finally a lack of type declaration is treated as mixed.

Liskov's substitutions rules dictate that return types are co-variant i.e.
more specific, and argument types are contra-variant i.e. more general.
This is why any return type can be replaced by never and any argument type
can have it's type dropped/changed to mixed.
As such replacing never by mixed in an argument is totally possible as
mixed is a wider type than never.

How I personally see never as an argument type is that you require a
mandatory argument but you leave the type constraint up to the
implementation.

A recent example which bit us in php-src/the PHP documentation is the
interface of ArrayAccess, all of the $offset parameters have a mixed type.
Until recently the ArrayObject/ArrayIterator had incorrect stubs [1] by
indicating that the argument was of type int|string, which practically is
the case as SPL's ArrayAccess handler will throw a TypeError on different
types, however this is done manually within the call and not when the call
is made.
Ideally the $offset parameter would be of type never such that SPL, and
userland, can specify what type of offsets they accept, be that the usual
int|string, only int for list-like objects, only string for dictionary-like
objects, maybe even object|int|string to allow GMP objects for arbitrary
precision.
Whereas every implementer of ArrayAccess is forced to accept mixed for the
$offset and need to manually enforce the type.

This is the "power" of the never type as an argument type.

Best regards,

George P. Banyard

[1]
https://github.com/php/php-src/pull/7215/files#diff-e330df347cac9e68d2d07a06535c534cd8c2438a1af703cd4245b8ce91ec65afL9-R10


[PHP-DEV] Re: Broken reference at https://wiki.php.net/rfc/howto

2021-08-14 Thread Christoph M. Becker
On 14.08.2021 at 00:43, Willian de Souza wrote:

> Hope I'm in the right place, I was reading
>  and I found a broken reference,
> the link to the explanation of the "bottom post"  in first step
> redirects to this page:
> 
>
> I don't know what is correct page, i can't find it.

I've updated the link.  Thanks for reporting the issue.

--
Christoph M. Becker

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



Re: [PHP-DEV] [RFC] Never For Argument Types

2021-08-14 Thread Deleu
Hi Jordan,

Does it make sense to explain in the RFC the difference between never and
mixed in this context? The RFC vaguely mentions that never can never be
used directly, but if it's limited to abstract class and interfaces, isn't
that already impossible to use directly? Or does it mean that the type
would "be allowed" on any function, but because of its intrinsic behavior
it would always fail if used in non-abstract methods?

Another clarification I'd be interested is about dropping the type
declaration entirely (e.g. https://3v4l.org/a4bfs), because of covariance
(or contravariance, I never know), sub classes can completely drop type
declaration entirely. Will never not allow this? Why? Why not? If it does
allow this, does it really differ from not having any type declaration on
the abstract function?

My knowledge in this area is practically null so if I'm asking stupid
questions that are easily explained by some blog post I'd he happy to read
it.

On Sat, Aug 14, 2021, 01:27 Jordan LeDoux  wrote:

> Hey internals,
>
> I've been working on the draft for my operator overloading RFC, and in
> doing so I encountered a separate change that I would like to see.
>
> That is, the use of `never` as an argument type for interfaces. Since
> arguments in PHP are contravariant to preserve Liskov substitution, `never`
> as the bottom type should indicate that implementing classes can require
> any type combination they want. This is in fact consistent with type theory
> and set theory, and is how the bottom type is treated in several other
> languages.
>
> In this case, the bottom type would be used to indicate covariant parameter
> polymorphism while not conflicting with LSP.
>
> This would provide a sort of minimal form of generics to PHP without the
> issues that actual generics present from an implementation perspective. It
> would not, however, restrict or hinder any future RFC for generics.
>
> This is at the first draft stage, and I currently have the RFC on a github
> repo to allow for easy contribution and collaboration.
>
> Any feedback is greatly appreciated.
>
> https://github.com/JordanRL/never-argument-type
>
> Jordan
>