Re: [PHP-DEV] [RFC] Pure intersection types

2021-04-03 Thread G. P. B.
On Tue, 23 Mar 2021 at 19:45, Matthew Brown 
wrote:

> On Tue, 23 Mar 2021 at 05:32, G. P. B.  wrote:
>
>> I'm calling this proposal pure intersection types as there would be no
>> possibility of mixing intersection and union types, I'm leaving this as a
>> future scope.
>>
>
> Does this miss an opportunity, though? It's useful to be able to write
> A&B|null.
>

Obviously this is less powerful than support for composite types where one
can use both intersections and unions.

I've tried implementing composite types without grouping here:
https://github.com/Girgias/php-src/pull/8
But I'm hitting various issues and I'm far from confident that I'll be able
to resolve them and add the variance check code before June so that this
can reasonably get voted in for PHP 8.1.

The end goal is support for composite types but I prefer to land a
reasonably self contained feature in 8.1 then nothing at all.
Internals might disagree with this and refuse the feature unless "complete"
but if that's the case there is still time to "finish" it for another RFC.

If someone else wants to work on adding support for composite types they
are free to work based on my PR, or collaborate with me.

I've also tidied up the RFC: https://github.com/Girgias/intersection-types

Unless someone shows up to work on composite types, I'll probably bring
this to a vote next week (if I don't forget about it).

Best regards,

George P. Banyard


Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Benjamin Eberlei
On Fri, Apr 2, 2021 at 3:14 AM Aaron Piotrowski  wrote:

>
> > On Apr 1, 2021, at 2:03 PM, Levi Morrison via internals <
> internals@lists.php.net> wrote:
> >
> > I do not care which name is chosen, but if we are going to have this
> > sort of thing in the language, it ought to be a bottom type, not an
> > attribute.
> >
>
> You make an excellent point Levi. I initially chose `noreturn` simply
> because I was familiar with the name from C and didn't have a strong
> opinion. However, I agree that `noreturn` is a poor choice for reuse as a
> bottom type, so I changed my vote to `never`.
>

i voted against this proposal, but changed my choice of "noreturn" to
"never", because it would ultimately be slightly less bad to have this name
for use as a bottom type. The name "never" is still unfortunate, because it
transmits "behavior" of being used in the context of a function, a better
name might have been "nothing" as Levi suggests.

But I again get to the point of the problem with this RFC due to naming.
"never" is actually combining "nothing" type with "noreturn" flag, so for
me the most consistent way would have been "public noreturn function foo():
nothing"

Its said that composition is better than inheritance, so combining two
behaviors into one keyword will be limiting in the future, if we think of
other function flags that should compose with "never".


> Cheers,
> Aaron Piotrowski
>
>


Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Rowan Tommins

On 03/04/2021 16:30, Benjamin Eberlei wrote:

But I again get to the point of the problem with this RFC due to naming.
"never" is actually combining "nothing" type with "noreturn" flag, so for
me the most consistent way would have been "public noreturn function foo():
nothing"



I'm not sure how the flag and return type could ever be used separately. 
Are you suggesting that we should allow all 3 of these:


- public noreturn function foo(): nothing
- public noreturn function foo(): int
- public function foo(): nothing

How would any tool treat these differently?

Regards,

--
Rowan Tommins
[IMSoP]

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



Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Benjamin Eberlei
On Sat, Apr 3, 2021 at 5:30 PM Benjamin Eberlei  wrote:

>
>
> On Fri, Apr 2, 2021 at 3:14 AM Aaron Piotrowski  wrote:
>
>>
>> > On Apr 1, 2021, at 2:03 PM, Levi Morrison via internals <
>> internals@lists.php.net> wrote:
>> >
>> > I do not care which name is chosen, but if we are going to have this
>> > sort of thing in the language, it ought to be a bottom type, not an
>> > attribute.
>> >
>>
>> You make an excellent point Levi. I initially chose `noreturn` simply
>> because I was familiar with the name from C and didn't have a strong
>> opinion. However, I agree that `noreturn` is a poor choice for reuse as a
>> bottom type, so I changed my vote to `never`.
>>
>
> i voted against this proposal, but changed my choice of "noreturn" to
> "never", because it would ultimately be slightly less bad to have this name
> for use as a bottom type. The name "never" is still unfortunate, because it
> transmits "behavior" of being used in the context of a function, a better
> name might have been "nothing" as Levi suggests.
>
> But I again get to the point of the problem with this RFC due to naming.
> "never" is actually combining "nothing" type with "noreturn" flag, so for
> me the most consistent way would have been "public noreturn function foo():
> nothing"
>

Sorry, i should have been more detailed/precise before:

Why i think "never" is not a great solution, if you have the same example
that TypeScript uses to explain their "never":

if (is_string($value) && is_int($value)) {
   // inside here $value is_type == "never"
}

The naming "never" here makes no sense, because from a theoretical
perspective reasoning about the type of $value it is nothing and only the
block of code is "never reached".

I suppose PHPStan and Psalm are eager to reuse the new type name for this
kind of type interference, same as TypeScript does. The name is sub
optiomal outside the context of a return type.

So lets say we seperate the two behaviors of "never" into "nothing +
noreturn".

public noreturn function foo(): nothing {
exit();
}

But adding a new keyword "noreturn" would not be necessary, it could just
be an Attribute as i said in my first e-mail explaining my no-vote:

#[NoReturn] // sets a function flag modifying the void behavior
public function foo(): nothing {
return; // throws if it reaches this point
}

This would be closer to what Psalm and PHP-Stan use at the moment if we
replace nothing with void.

The problem is that "void" is already not perfect, since the callside
doesn't care about "return null" with no return type vs "return" + void
return type.

If we had "nothing" and "null" instead of "void", and we'd say like PHP
works, "return;" actually means "return null;", then:

function foo(): nothing {
return; // Error: cannot return null from a function that returns
nothing.
}
function bar(): null {
return;
// or return null;
}

This would more consistently tie into union types where |null is allowed,
however on its own it is not: "foo() : null => error".

As Levi said, this noreturn/never just perpetuates/amplifies the existing
void mistake and feels off, given that other recent changes to PHP have
been more bold, towards removing inconsistencies.


> Its said that composition is better than inheritance, so combining two
> behaviors into one keyword will be limiting in the future, if we think of
> other function flags that should compose with "never".
>
>
>> Cheers,
>> Aaron Piotrowski
>>
>>


Re: [PHP-DEV] [VOTE] Object scoped RNG implementation

2021-04-03 Thread Aaron Piotrowski



> On Apr 2, 2021, at 5:49 PM, Larry Garfield  wrote:
> 
> On Fri, Apr 2, 2021, at 4:56 PM, Kamil Tekiela wrote:
>> Hi Go Kudo,
>> 
>> First, let me say that I believe we need such implementation in PHP and I
>> would like to see object scoped RNG as part of the standard. However, I
>> have voted no for a number of reasons. Let me list them from the
>> perspective of a noob PHP user.
>> 
>> - I really do not understand why we are introducing new functions. Can't
>> the classes implement the necessary methods to get integers, doubles, and
>> string of bytes? As a new user I would be completely overwhelmed by all
>> these functions: rand(), mt_rand(), rng_int(), rng_next(), rng_next64().
>> Which one should I use? What is the difference between rng_next()
>> and rng_next64?
>> - As soon as I left the RFC page I forgot what the new classes were called.
>> I still can't tell from memory what's their name. I understand what they
>> mean, but they are definitely not friendly names.
>> - What's the difference between MT19937 and XorShift128Plus? They are
>> different algorithms but which one should I pick? I tested the
>> implementation locally and I see no difference in performance.
>> - I am not a fan of adding a new optional parameter to shuffle() and
>> friends. I'd prefer to have a method in the class that I can pass an array
>> to.
>> - What is the default seed? Do I have to provide a seed each time? Why
>> can't the seed be done automatically?
>> - Signed? Unsigned? As far as I know, PHP doesn't have unsigned integers.
>> What's the real-life purpose of this flag?
>> - I don't see any use in supporting userland implementations. Why can't
>> they create separate libraries?  I don't know about performance, but if
>> someone wants to have custom RNG then I don't think they worry about
>> performance.
>> - When using the functions the performance was 50% worse than when calling
>> ->next() directly. Is this right or is the implementation going to be
>> optimized further? The fastest way to get a random number seems to be
>> mt_rand() based on my tests.
>> 
>> I would rather like to see a single class called RNG/Random that implements
>> RNG/RandomInterface. The constructor of the class would take 2 arguments.
>> The first is the algorithm with a default either MT or XORShift. The second
>> is an optional seed. If no seed is provided then the seed is generated
>> automatically like in mt_srand(). The class would then implement methods
>> like: nextInt(), nextDouble(), nextBytes(), arrayShuffle(),
>> stringShuffle(), randomArrayKeys(). I would keep the standard functions as
>> they are. Let them use MT by default. We could even deprecate them in
>> future if this takes off.
>> 
>> This would make it painfully obvious what the class does and how to use it.
>> No more procedural code. I would also make the class final so that you
>> can't inherit from it, but that is highly opinion-based.
>> Now that I have written this, I read previous conversations and it looks to
>> me like what I would like is what you had previously.
>> 
>> I'm sorry if I complain too much, but I would like to see something like
>> this implemented, just not like you are proposing right now. It is too
>> messy for me and I know I wouldn't like it if I had to use it.
>> 
>> Regards,
>> Kamil
> 
> I also didn't pay close attention to the previous discussion, but reading the 
> RFC I agree with all of this.  The functionality proposed is good and needed, 
> but the API is a mess.  What Kamil suggests is far better, and fully commits 
> to being OOPy.  Given that the use case is for situations where you need a 
> predictable and repeatable random sequence, such as Fibers or threads or 
> such, going all-in on an object seems like the correct approach.
> 
> One thing I'm not 100% clear on from the RFC, does this also deprecate 
> random_int()/random_bytes()?  Those are (AFAIK) unseeded, so they seem like 
> they'd continue to serve their current purpose, but it's not clear from the 
> RFC.
> 
> Voting no for now, but I would welcome a resubmission with a cleaner API, 
> even in this cycle.
> 
> --Larry Garfield
> 

I too voted no for similar reasons as Larry, Marco, Levi, and others. The API 
needs improvement and using a new namespace without precedent or a plan is 
problematic.

Overall I’m in favor of an object-based approach and encourage you to rework 
the API and bring it to a vote for PHP 8.1.

Cheers,
Aaron Piotrowski

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



Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Andreas Leathley

On 03.04.21 18:30, Benjamin Eberlei wrote:

if (is_string($value) && is_int($value)) {
// inside here $value is_type == "never"
}

The naming "never" here makes no sense, because from a theoretical
perspective reasoning about the type of $value it is nothing and only the
block of code is "never reached".

I suppose PHPStan and Psalm are eager to reuse the new type name for this
kind of type interference, same as TypeScript does. The name is sub
optiomal outside the context of a return type.


I read through all the Typescript and Hack explanations/examples of
"never" and "nothing", and to me "never" seems clearer, which just shows
how different opinions can be. I would not like "nothing" because it
seems so similar to "void" and "null". "This function returns nothing"
would inevitably lead to the question what that actually means. "This
function returns never" is a reasonably clear description. "This
variable at this point is never" or "This variable at this point is
nothing" are both not clear without context, although never implies this
should not happen (or cannot happen) and could be interpreted as "This
variable at this point is never anything", which in general would be
clearer to me (not being familiar with either before this proposal).

From a practical perspective, I think the proposal is about the return
type because this has a clear use case in code today. Your $value
example would lead to the Psalm/PHPStan errors of "Type does not contain
type" (Psalm) or "Result of && is always false" (PHPStan), I don't think
there currently is much use to determine a type of never in these cases.
But that might be something Matt/Ondrej can answer a lot better than me.

I initially preferred "noreturn", but now prefer "never". "noreturn" is
more self-explanatory, but "never" seems more apt and versatile, while
still being quite clear.

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



Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Peter Bowyer
On Sat, 3 Apr 2021 at 17:30, Benjamin Eberlei  wrote:

> The problem is that "void" is already not perfect, since the callside
> doesn't care about "return null" with no return type vs "return" + void
> return type.
>
> If we had "nothing" and "null" instead of "void", and we'd say like PHP
> works, "return;" actually means "return null;", then:
>
> function foo(): nothing {
> return; // Error: cannot return null from a function that returns
> nothing.
> }
> function bar(): null {
> return;
> // or return null;
> }
>
> This would more consistently tie into union types where |null is allowed,
> however on its own it is not: "foo() : null => error".
>
> As Levi said, this noreturn/never just perpetuates/amplifies the existing
> void mistake and feels off, given that other recent changes to PHP have
> been more bold, towards removing inconsistencies.
>

This and Levi's email make compelling arguments and I would like to see
this adopted. I have changed my vote to "No".

Peter


Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Andreas Leathley

On 03.04.21 21:26, Peter Bowyer wrote:

This and Levi's email make compelling arguments and I would like to see
this adopted. I have changed my vote to "No".

Wasn't Levi arguing for the RFC? Introducing "never" as a bottom type is
what Levi was strongly arguing for, and that is what the RFC currently
proposes/leads to (taking into account the clear lead for "never").

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



Re: [PHP-DEV] [RFC] Pure intersection types

2021-04-03 Thread Saif Eddin Gmati
Personally, I am against the syntax used in the PR for composite
types( even tho i don't have voting powers ).

I would prefer a syntax similar to Hack, where you have to use parentheses to 
make things more explicit.

considering the following Hack code:


interface A {}
interface B {}
interface C {}
interface D {}
interface E {}
interface F {}

function bar(
  ((A & F) | (((A & B) | (C & D)) & E)) $_foo
): void {}


In PHP, i would assuming i can just remove the parentheses and it would work as 
expected:


https://twitter.com/azjezz/status/1373439678045683721 / 
https://twitter.com/azjezz/status/1373647148026322946

Regards,

Saif.


‐‐‐ Original Message ‐‐‐
On Saturday, April 3, 2021 1:22 PM, G. P. B.  wrote:

> On Tue, 23 Mar 2021 at 19:45, Matthew Brown matthewmatt...@gmail.com
> wrote:
>
> > On Tue, 23 Mar 2021 at 05:32, G. P. B. george.bany...@gmail.com wrote:
> >
> > > I'm calling this proposal pure intersection types as there would be no
> > > possibility of mixing intersection and union types, I'm leaving this as a
> > > future scope.
> >
> > Does this miss an opportunity, though? It's useful to be able to write
> > A&B|null.
>
> Obviously this is less powerful than support for composite types where one
> can use both intersections and unions.
>
> I've tried implementing composite types without grouping here:
> https://github.com/Girgias/php-src/pull/8
> But I'm hitting various issues and I'm far from confident that I'll be able
> to resolve them and add the variance check code before June so that this
> can reasonably get voted in for PHP 8.1.
>
> The end goal is support for composite types but I prefer to land a
> reasonably self contained feature in 8.1 then nothing at all.
> Internals might disagree with this and refuse the feature unless "complete"
> but if that's the case there is still time to "finish" it for another RFC.
>
> If someone else wants to work on adding support for composite types they
> are free to work based on my PR, or collaborate with me.
>
> I've also tidied up the RFC: https://github.com/Girgias/intersection-types
>
> Unless someone shows up to work on composite types, I'll probably bring
> this to a vote next week (if I don't forget about it).
>
> Best regards,
>
> George P. Banyard

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



Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Matthew Brown
On Sat, 3 Apr 2021 at 12:30, Benjamin Eberlei  wrote:

>
> But adding a new keyword "noreturn" would not be necessary, it could just
> be an Attribute as i said in my first e-mail explaining my no-vote:
>
> #[NoReturn] // sets a function flag modifying the void behavior
> public function foo(): nothing {
> return; // throws if it reaches this point
> }
>
> This would be closer to what Psalm and PHP-Stan use at the moment if we
> replace nothing with void.
>
> The problem is that "void" is already not perfect, since the callside
> doesn't care about "return null" with no return type vs "return" + void
> return type.
>
> If we had "nothing" and "null" instead of "void", and we'd say like PHP
> works, "return;" actually means "return null;", then:
>
> function foo(): nothing {
> return; // Error: cannot return null from a function that returns
> nothing.
> }
> function bar(): null {
> return;
> // or return null;
> }
>
> This would more consistently tie into union types where |null is allowed,
> however on its own it is not: "foo() : null => error".
>
> As Levi said, this noreturn/never just perpetuates/amplifies the existing
> void mistake and feels off, given that other recent changes to PHP have
> been more bold, towards removing inconsistencies.
>
>
Clearly comparisons of "noreturn"/"never" to "void" are a bit of a
minefield, because a number of contributors feel that void was a mistake,
that its implementation doesn't feel PHP-like.

While I disagree that our proposal is intrinsically connected with the void
one – noreturn/never could work equally well with a "null" return — our
proposal does perpetuate one idea behind "void": that PHP can benefit from
types found in other languages and type systems, and especially types found
in Hack.

It seems like some of the debate is over whether "noreturn"/"never" is a
behaviour or a type. If it were purely a behaviour, with no meaning as a
type, an Attribute would be a much more appropriate location.

It's not just a behaviour, though — it is a type that follows variance
rules, and it's a type that PHP can check.

If "void" returns are too much of a distraction, think instead of "object"
return type declarations:

When executing the function

function returnsObject($o) : object {
if (rand(0, 1)) {
return $o;
}
}

Here PHP's engine checks two separate behaviours

1. when the function explicitly returns, does it return an object?
2. does the function ever finish without returning or throwing or exiting?

Only the first actually involves a strict type check. The second is a
generic behaviour check, triggered by the existence of a return type. This
is essentially the same check that we want to trigger with
"noreturn"/"never".

In fact, as someone recently pointed out, running the following code
*today* produces similar errors to the ones we propose:

function php7Redirect() : noreturn {
if (rand(0, 1)) {
return "bad"; //  Fatal error: Uncaught TypeError
}
header("Location: https://php.net";);
exit; // OK
}

Our RFC makes this code explicitly legal, and adds covariance. Indeed our
implementation is small because it correctly treats "noreturn"/"never" as a
type, allowing us to use the existing return type handling.


Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread David Rodrigues
Just to spice up the discussion a bit, I will try to give my opinion on
this RFC...

It is very likely that the proposal will be accepted (it is already 33/10),
but I still find the terms "noreturn" or "never" unclear. "noreturn" are
two words together, and I am not particularly a fan of this type of
nomenclature (and it may sound repetitive and strange "return no return"),
while "never" can be ambiguous, it could be read as "never return" (OK) or
"return never" (and it sounds a little strange, I guess).

I saw someone (sorry, I don't remember who) suggesting the term "terminus",
so I thought of an alternative like "terminal". Or, if you still want to
take advantage of a keyword and without losing the meaning, "exit"
(including, it makes absolutely clear what is expected as "return": "return
the exit").

Is there any chance of discussing terms, even if the "never" indication is
winning at the moment? Or did I miss this discussion?

Thanks!


Atenciosamente,
David Rodrigues


Em sáb., 3 de abr. de 2021 às 23:07, Matthew Brown 
escreveu:

> On Sat, 3 Apr 2021 at 12:30, Benjamin Eberlei  wrote:
>
> >
> > But adding a new keyword "noreturn" would not be necessary, it could just
> > be an Attribute as i said in my first e-mail explaining my no-vote:
> >
> > #[NoReturn] // sets a function flag modifying the void behavior
> > public function foo(): nothing {
> > return; // throws if it reaches this point
> > }
> >
> > This would be closer to what Psalm and PHP-Stan use at the moment if we
> > replace nothing with void.
> >
> > The problem is that "void" is already not perfect, since the callside
> > doesn't care about "return null" with no return type vs "return" + void
> > return type.
> >
> > If we had "nothing" and "null" instead of "void", and we'd say like PHP
> > works, "return;" actually means "return null;", then:
> >
> > function foo(): nothing {
> > return; // Error: cannot return null from a function that returns
> > nothing.
> > }
> > function bar(): null {
> > return;
> > // or return null;
> > }
> >
> > This would more consistently tie into union types where |null is allowed,
> > however on its own it is not: "foo() : null => error".
> >
> > As Levi said, this noreturn/never just perpetuates/amplifies the existing
> > void mistake and feels off, given that other recent changes to PHP have
> > been more bold, towards removing inconsistencies.
> >
> >
> Clearly comparisons of "noreturn"/"never" to "void" are a bit of a
> minefield, because a number of contributors feel that void was a mistake,
> that its implementation doesn't feel PHP-like.
>
> While I disagree that our proposal is intrinsically connected with the void
> one – noreturn/never could work equally well with a "null" return — our
> proposal does perpetuate one idea behind "void": that PHP can benefit from
> types found in other languages and type systems, and especially types found
> in Hack.
>
> It seems like some of the debate is over whether "noreturn"/"never" is a
> behaviour or a type. If it were purely a behaviour, with no meaning as a
> type, an Attribute would be a much more appropriate location.
>
> It's not just a behaviour, though — it is a type that follows variance
> rules, and it's a type that PHP can check.
>
> If "void" returns are too much of a distraction, think instead of "object"
> return type declarations:
>
> When executing the function
>
> function returnsObject($o) : object {
> if (rand(0, 1)) {
> return $o;
> }
> }
>
> Here PHP's engine checks two separate behaviours
>
> 1. when the function explicitly returns, does it return an object?
> 2. does the function ever finish without returning or throwing or exiting?
>
> Only the first actually involves a strict type check. The second is a
> generic behaviour check, triggered by the existence of a return type. This
> is essentially the same check that we want to trigger with
> "noreturn"/"never".
>
> In fact, as someone recently pointed out, running the following code
> *today* produces similar errors to the ones we propose:
>
> function php7Redirect() : noreturn {
> if (rand(0, 1)) {
> return "bad"; //  Fatal error: Uncaught TypeError
> }
> header("Location: https://php.net";);
> exit; // OK
> }
>
> Our RFC makes this code explicitly legal, and adds covariance. Indeed our
> implementation is small because it correctly treats "noreturn"/"never" as a
> type, allowing us to use the existing return type handling.
>


Re: [PHP-DEV] [VOTE] noreturn type

2021-04-03 Thread Matthew Brown
On Sat, 3 Apr 2021 at 22:29, David Rodrigues  wrote:

> It is very likely that the proposal will be accepted (it is already 33/10),
>

I'm definitely not counting my chickens.


> Is there any chance of discussing terms, even if the "never" indication is
> winning at the moment? Or did I miss this discussion?
>

The RFC discussion is here: https://externals.io/message/113442. Someone
suggested "terminus", but nobody replied supporting that suggestion (that
was your opportunity!). Lots of people suggested "never", enough that a
vote on "noreturn" vs "never" was added to the final RFC.

As for "terminus", I don't think there's much benefit to PHP having its own
separate term for a type "noreturn"/"never" that already exists in other
languages. I know that naming is one of the "two hard things", but there's
no need to make it any harder.