Dear Internals,
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed. - declare(strict_types=1) {} (block mode) is specifically disallowed.
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.
As this topic has and is being discussed to death, I have put a very
large "discussion points" section:
https://wiki.php.net/rfc/scalar_type_hints_v5#discussion_points
I would kindly ask, before replying that you check to see if your
question is answered in that list.
If it is not, please follow up here and I will update the RFC.
If your question is listed and you feel that it wasn't given proper
due, please let's discuss that.
https://wiki.php.net/rfc/scalar_type_hints_v5
Considering this proposal is a minor tweak on an already-discussed and
voted-on proposal, I plan on bringing this RFC to vote 1 week from
today (on February 25th, 2015).
Thanks,
Anthony
Dear Internals,
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed.- declare(strict_types=1) {} (block mode) is specifically disallowed.
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.As this topic has and is being discussed to death, I have put a very
large "discussion points" section:
https://wiki.php.net/rfc/scalar_type_hints_v5#discussion_pointsI would kindly ask, before replying that you check to see if your
question is answered in that list.
General comments from me, as a radical strictist. No need to reply and
tell me I'm "wrong", these are my opinions.
Internal Functions Like
ceil()
Return Unexpected Types
My opinion is that functions should return sane types for their
intended purpose, and functions that do not should be "fixed".
Integers Should Be Accepted For Strict float Arguments
Int->Float Exception Makes Strict Mode "Flawed"
My opinion is that strict should mean strict.
Static Analysis Is Possible With Weak Declarations
The advocacy of allowing accepts_float(returns_int());
doesn't help
the cause of static analysers in strict mode.
Why Not Add Support For Null?
I agree a null type is pointless, however I would like to raise the
discussion point of existing hinted optional parameters being allowed
a default of null. i.e. fn(Obj $o = null) {}
Do you think this is acceptable for any other types? I can only think
of it being useful if resource and a generic object type are added.
but others may disagree. (Ideally the resource type will go away over
time and will be replaced with objects like GMP anyway :))
Still no mention of a way to enable strict by default. So lets try
some different rationale. If I personally want to develop in strict
mode, I can do that with this proposal, I can add a declare to the top
of every file and be as strict as I like. However not everyone else is
going to want to use my code in strict mode, so they will have to go
and remove some/all of those strict declarations. (Lets take callbacks
being evaluated in the context they are called rather than the one
they are created in). I would like a way of enabling strict by
default, immutable to scripts so that users cannot be forced into this
mode, and lets the radicals and the weaklings* play together in
harmony.
For the rest of the RFC, I either agree with or have no strong
opinions about the points raised.
*it's a joke you guys.
Hi,
I would like a way of enabling strict by
default, immutable to scripts so that users cannot be forced into this
mode, and lets the radicals and the weaklings* play together in
harmony.For the rest of the RFC, I either agree with or have no strong
opinions about the points raised.*it's a joke you guys.
I am still bipolar and I still want both to co-exist with no switches
and modes. :)
No joke.
Cheers,
Andrey.
Leigh,
Internal Functions Like
ceil()
Return Unexpected TypesMy opinion is that functions should return sane types for their
intended purpose, and functions that do not should be "fixed".
I agree 100%. I just think that's outside the scope of this proposal.
Static Analysis Is Possible With Weak Declarations
The advocacy of allowing
accepts_float(returns_int());
doesn't help
the cause of static analysers in strict mode.
Java does exactly this and is statically analyzable. So...?
Still no mention of a way to enable strict by default. So lets try
some different rationale. If I personally want to develop in strict
mode, I can do that with this proposal, I can add a declare to the top
of every file and be as strict as I like. However not everyone else is
going to want to use my code in strict mode, so they will have to go
and remove some/all of those strict declarations. (Lets take callbacks
being evaluated in the context they are called rather than the one
they are created in). I would like a way of enabling strict by
default, immutable to scripts so that users cannot be forced into this
mode, and lets the radicals and the weaklings* play together in
harmony.
I missed that discussion point, so I've just added it:
https://wiki.php.net/rfc/scalar_type_hints_v5#why_not_add_an_ini_setting_for_default_mode
For the rest of the RFC, I either agree with or have no strong
opinions about the points raised.
Thanks for the input :-)
Anthony
Static Analysis Is Possible With Weak Declarations
The advocacy of allowing
accepts_float(returns_int());
doesn't help
the cause of static analysers in strict mode.Java does exactly this and is statically analyzable. So...?
As discussed elsewhere. You're absolutely right, it is up to the
analyser to throw a warning on this because it is a type-based
conversion rather than value based one.
On Thu, Feb 19, 2015 at 12:50 AM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Leigh,
Internal Functions Like
ceil()
Return Unexpected TypesMy opinion is that functions should return sane types for their
intended purpose, and functions that do not should be "fixed".I agree 100%. I just think that's outside the scope of this proposal.
Static Analysis Is Possible With Weak Declarations
The advocacy of allowing
accepts_float(returns_int());
doesn't help
the cause of static analysers in strict mode.Java does exactly this and is statically analyzable. So...?
PHP is not a language for static analyzes or verification!!!
Strict typing shouldn't be done on language level.
it may be implemented as a custom verification extension, but please, don't
break the language itself.
Thanks. Dmitry.
Still no mention of a way to enable strict by default. So lets try
some different rationale. If I personally want to develop in strict
mode, I can do that with this proposal, I can add a declare to the top
of every file and be as strict as I like. However not everyone else is
going to want to use my code in strict mode, so they will have to go
and remove some/all of those strict declarations. (Lets take callbacks
being evaluated in the context they are called rather than the one
they are created in). I would like a way of enabling strict by
default, immutable to scripts so that users cannot be forced into this
mode, and lets the radicals and the weaklings* play together in
harmony.I missed that discussion point, so I've just added it:
https://wiki.php.net/rfc/scalar_type_hints_v5#why_not_add_an_ini_setting_for_default_mode
For the rest of the RFC, I either agree with or have no strong
opinions about the points raised.Thanks for the input :-)
Anthony
Hi Anthony!
Thanks for bringing this up again. I am asking you the same I asked Andrea
2 weeks ago on Twitter: make it a triple option vote please. She didn't
want to do it, hope you do! This way you eliminate the neverending
discussion about weak vs strict, let the votes decide and see who really
prefers weak type hinting only and who prefers the stricter way, both camps
will have an option to vote.
So I propose 3 voting options: Yes (strict), Yes (weak), No. The Yes votes
combined need 2/3 of the votes. Then a simple majority of 50%+1 between the
different Yes votes is needed.
Thanks!
Albert
On Wed, Feb 18, 2015 at 9:44 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dear Internals,
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed.- declare(strict_types=1) {} (block mode) is specifically disallowed.
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.As this topic has and is being discussed to death, I have put a very
large "discussion points" section:
https://wiki.php.net/rfc/scalar_type_hints_v5#discussion_pointsI would kindly ask, before replying that you check to see if your
question is answered in that list.If it is not, please follow up here and I will update the RFC.
If your question is listed and you feel that it wasn't given proper
due, please let's discuss that.https://wiki.php.net/rfc/scalar_type_hints_v5
Considering this proposal is a minor tweak on an already-discussed and
voted-on proposal, I plan on bringing this RFC to vote 1 week from
today (on February 25th, 2015).Thanks,
Anthony
On 18 February 2015 at 22:21, Albert Casademont Filella
albertcasademont@gmail.com wrote:
So I propose 3 voting options: Yes (strict), Yes (weak), No. The Yes votes
combined need 2/3 of the votes. Then a simple majority of 50%+1 between the
different Yes votes is needed.
This is pretty flawed, but nice try.
Albert,
On Wed, Feb 18, 2015 at 5:21 PM, Albert Casademont Filella
albertcasademont@gmail.com wrote:
Hi Anthony!
Thanks for bringing this up again. I am asking you the same I asked Andrea 2
weeks ago on Twitter: make it a triple option vote please. She didn't want
to do it, hope you do! This way you eliminate the neverending discussion
about weak vs strict, let the votes decide and see who really prefers weak
type hinting only and who prefers the stricter way, both camps will have an
option to vote.So I propose 3 voting options: Yes (strict), Yes (weak), No. The Yes votes
combined need 2/3 of the votes. Then a simple majority of 50%+1 between the
different Yes votes is needed.
Thanks for the feedback. I have added it to the discussion points:
https://wiki.php.net/rfc/scalar_type_hints_v5#this_proposal_should_have_multiple_vote_options
The text:
This is not a two-part proposal. The proposal is of a unified system
that was designed to work together. As such, neither part (weak-only
or strict-only) is designed to stand on its own without the other
part.
Therefore, it only makes sense to vote on this proposal as a whole.
Therefore, the voting options this RFC will present will be: Yes and
No.
Thanks,
Anthony
Anthony Ferrara wrote:
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.
Have you considered the overflow behavior of ints resulting in a float?
For instance, the following code would produce E_RECOVERABLE_ERROR, AIUI:
<?php
declare(strict_types=1);
function foo(int a, int b) {
bar(a * b);
}
function bar(int n) {
}
foo(10000000000, 10000000000);
It seems to me that this behavior is hard to deal with generally for
programmers as well as static analyzers. Andreas' bigint RFC[1] would
solve that issue, but it has been withdrawn, and AFAIK nobody is working
on it. OTOH, bigint would make the widening from int to float
potentially even more lossy (i.e. inaccurate) than it is now (64bit ints
vs. IEEE 754 doubles).
IIRC, Pascal does not promote int to float on overflow, but rather
discards the high bits (unless overflow checking is enabled; available
only in some "newer" dialects). I don't know how Java handles this
case, but I assume there's no promotion to float either.
[1] https://wiki.php.net/rfc/bigint
--
Christoph M. Becker
Christoph,
Anthony Ferrara wrote:
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.Have you considered the overflow behavior of ints resulting in a float?
For instance, the following code would produce E_RECOVERABLE_ERROR, AIUI:<?php
declare(strict_types=1);
function foo(int a, int b) {
bar(a * b);
}function bar(int n) {
}foo(10000000000, 10000000000);
It seems to me that this behavior is hard to deal with generally for
programmers as well as static analyzers. Andreas' bigint RFC[1] would
solve that issue, but it has been withdrawn, and AFAIK nobody is working
on it. OTOH, bigint would make the widening from int to float
potentially even more lossy (i.e. inaccurate) than it is now (64bit ints
vs. IEEE 754 doubles).IIRC, Pascal does not promote int to float on overflow, but rather
discards the high bits (unless overflow checking is enabled; available
only in some "newer" dialects). I don't know how Java handles this
case, but I assume there's no promotion to float either.
That is a very good point. We had discussed that a while ago, but it
hasn't come up in a while here. I've added a section in the RFC on it:
https://wiki.php.net/rfc/scalar_type_hints_v5#integer_overflow_to_float_behavior
Basically, I don't see any sane alternative but to have it cause an
error at runtime. It's not precision loss, it's magnitude loss.
The only other thing I can think of is to have the operators not
promote in strict mode, but that's even worse since now you're
clamping and not even giving the ability to detect it.
I don't think in practice it will be a huge issue, but even if it
comes up, it'll at least error sanely...
Thanks
Anthony
Anthony,
Anthony Ferrara wrote:
Have you considered the overflow behavior of ints resulting in a float?
For instance, the following code would produce E_RECOVERABLE_ERROR, AIUI:<?php
declare(strict_types=1);
function foo(int a, int b) {
bar(a * b);
}function bar(int n) {
}foo(10000000000, 10000000000);
That is a very good point. We had discussed that a while ago, but it
hasn't come up in a while here. I've added a section in the RFC on it:
https://wiki.php.net/rfc/scalar_type_hints_v5#integer_overflow_to_float_behavior
Thanks for adding a respective note to the RFC, because IMHO it's quite
important to consider the behavior. Somehow I would like to have
Scheme's numeric system, but that doesn't seem to fit well with type
hinting (neither strict nor weak) -- at least not when it's about
performance.
Basically, I don't see any sane alternative but to have it cause an
error at runtime. It's not precision loss, it's magnitude loss.The only other thing I can think of is to have the operators not
promote in strict mode, but that's even worse since now you're
clamping and not even giving the ability to detect it.I don't think in practice it will be a huge issue, but even if it
comes up, it'll at least error sanely...
ACK.
--
Christoph M. Becker
It seems to me that this behavior is hard to deal with generally for
programmers as well as static analyzers. Andreas' bigint RFC[1] would
solve that issue, but it has been withdrawn, and AFAIK nobody is working
on it. OTOH, bigint would make the widening from int to float
potentially even more lossy (i.e. inaccurate) than it is now (64bit ints
vs. IEEE 754 doubles).
The 'unconstrained integer' RFC adds it' own problems, but the int ->
float overflow is only a problem with 32bit builds anyway. 64bit builds
will not overflow until they run out of space anyway.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Lester Caine wrote:
It seems to me that this behavior is hard to deal with generally for
programmers as well as static analyzers. Andreas' bigint RFC[1] would
solve that issue, but it has been withdrawn, and AFAIK nobody is working
on it. OTOH, bigint would make the widening from int to float
potentially even more lossy (i.e. inaccurate) than it is now (64bit ints
vs. IEEE 754 doubles).The 'unconstrained integer' RFC adds it' own problems, but the int ->
float overflow is only a problem with 32bit builds anyway. 64bit builds
will not overflow until they run out of space anyway.
It seems to me you're thinking too much (maybe only?) about "database
types". IMHO PHP can be used more versatile, and there might be issues
which are exemplified in the RFC[1]:
var_dump(2 ** 64); // float(1.844674407371E+19)
Clearly an int->float overflow that'll also happen on 64bit builds.
[1]
https://wiki.php.net/rfc/scalar_type_hints_v5#integer_overflow_to_float_behavior
--
Christoph M. Becker
It seems to me you're thinking too much (maybe only?) about "database
types". IMHO PHP can be used more versatile, and there might be issues
which are exemplified in the RFC[1]:
Maybe PHP can be more versatile, but what percentage of PHP code sits
between a web browser and a SQL database?
I think it is pretty high!
Lester Caine wrote:
It seems to me that this behavior is hard to deal with generally for
programmers as well as static analyzers. Andreas' bigint RFC[1] would
solve that issue, but it has been withdrawn, and AFAIK nobody is working
on it. OTOH, bigint would make the widening from int to float
potentially even more lossy (i.e. inaccurate) than it is now (64bit ints
vs. IEEE 754 doubles).The 'unconstrained integer' RFC adds it' own problems, but the int ->
float overflow is only a problem with 32bit builds anyway. 64bit builds
will not overflow until they run out of space anyway.It seems to me you're thinking too much (maybe only?) about "database
types". IMHO PHP can be used more versatile, and there might be issues
which are exemplified in the RFC[1]:var_dump(2 ** 64); // float(1.844674407371E+19)
Clearly an int->float overflow that'll also happen on 64bit builds.
[1]
https://wiki.php.net/rfc/scalar_type_hints_v5#integer_overflow_to_float_behavior
You see this has nothing to do with 'Scalar Type Declarations' ... this
is a problem in it's own right that needs sorting as part of the general
64bit 'upgrading' and providing a proper fix for 64bit numbers is
something which the 'unconstrained integer' RFC addressed but in my book
it was always the wrong fix, and providing a cross platform fix for
BIGINT which provides a simple integer value is the correct fix. The
voting on that RFC seemed to agree. We need 64bit values in several
places where simply clipping to 32bit ones is no longer the correct fix.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Am 18.02.2015 um 21:44 schrieb Anthony Ferrara:
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:
What about Sara's "Scalar Type Hints v0.4" discussion? I find it
disturbing that you take over the RFC without even mentioning this
discussion. Please coordinate with Sara first before starting another
attempt that will be doomed because some people rather wait for Sara's
RFC and a "<?php // strict" option.
Thanks
Dennis
Am 19.02.2015 um 05:21 schrieb Dennis Birkholz:
Am 18.02.2015 um 21:44 schrieb Anthony Ferrara:
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:What about Sara's "Scalar Type Hints v0.4" discussion? I find it
disturbing that you take over the RFC without even mentioning this
discussion. Please coordinate with Sara first before starting another
attempt that will be doomed because some people rather wait for Sara's
RFC and a "<?php // strict" option.
I just saw the reddit where you mention that v0.4 is practically
abandoned now, so I will just renounce my previous mail!
Will you consider to let the people vote on how to enable strict mode
like discussed in the v0.4 discussion? Like this here from the "Reviving
scalar type hints" thread?
Am 17.02.2015 um 00:58 schrieb Sara Golemon:> Straw poll:
- <?php strict;
- <?php-strict
- use strict; (psuedo-namespace)
- <?php // strict (I don't actually like HHVM's style, but if you do...)
- declare(strict=true); (As a top-level declare only)
- declare(strict=true); (exactly as in v0.3 -- maybe you liked it)
- your write-in vote here
Thanks
Dennis
I just saw the reddit where you mention that v0.4 is practically
abandoned now, so I will just renounce my previous mail!
DO NOT USE OTHER CHANNELS!
With the large number of secondary channels the only place that
suggestions like that should be made is here and as far as I have seen
both ideas are still 'active'? But I do find it crass that there is now
a different document with no reference to the v4 history!
What does need unravelling is just which bits go with which discussion
across all of the areas. I'm still looking at how any of this applies to
the values in the arrays I'm passing around and just getting more and
more confused. What I think I want is a set of functions to replace all
this casting mess. Rather than is_bool ... as_bool similarly as_int64
rather than getting an automatic float. I want to ask to look at a
variable in the array as the type I need for the job in hand now you may
say that is 'casting' but you are not providing me with the casts I
and many other database users need.
I can see the 'advantage' of optimizing code via this strict stuff that
some people want, but I don't see that has any place in a 'run only'
version of PHP. If you want to compile the code then use a port of PHP
that is compiled. Leave those of use who prefer the more dynamic system
which may well have to deal differently with a scalar variable depending
on what is returned at runtime.
On the minus side of this drive to 'optimize' the code is the potential
for completely different code on 32bit systems over 64bit ones. If the
number is below 32bit then a completely different set of code gets used
using only 32bit instructions. This may well be good for speed, but can
introduce cross platform differences that may be difficult to debug. We
currently live with those problems already with the int->float agro on
64bit numbers.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
De : Lester Caine [mailto:lester@lsces.co.uk]
I just saw the reddit where you mention that v0.4 is practically
abandoned now, so I will just renounce my previous mail!DO NOT USE OTHER CHANNELS!
Agreed.
And the RFC was not abandoned at all. I and others have been working almost continuously on a 'compromise' single-mode approach during the last 3 days (and nights), as activity on the list shows with no doubt. So, pretending the RFC to be 'abandoned' is just a way to discard a disagreed work.
As long as she does not officially gives up (posting to the list), I'll keep considering Sara still has the lead on scalar type hinting. If she officially gives up, I'll immediately propose to take it over and, if we are several to want it, we'll discuss.
That's the rule and I encourage list members to explicitly show their support to the formal process we all agreed upon.
For the rest, Lester summarized quite well my view about designing PHP for static analysis, instead of static analysis for PHP ;)
Regards
François
Francois and Lester (and all),
Please keep this thread on-topic. It should be for technical
discussions around this RFC only. If you have something non-technical
to discuss, please start a new topic.
Thanks
Anthony
De : Lester Caine [mailto:lester@lsces.co.uk]
I just saw the reddit where you mention that v0.4 is practically
abandoned now, so I will just renounce my previous mail!DO NOT USE OTHER CHANNELS!
Agreed.
And the RFC was not abandoned at all. I and others have been working almost continuously on a 'compromise' single-mode approach during the last 3 days (and nights), as activity on the list shows with no doubt. So, pretending the RFC to be 'abandoned' is just a way to discard a disagreed work.
As long as she does not officially gives up (posting to the list), I'll keep considering Sara still has the lead on scalar type hinting. If she officially gives up, I'll immediately propose to take it over and, if we are several to want it, we'll discuss.
That's the rule and I encourage list members to explicitly show their support to the formal process we all agreed upon.
For the rest, Lester summarized quite well my view about designing PHP for static analysis, instead of static analysis for PHP ;)
Regards
François
Dennis,
Will you consider to let the people vote on how to enable strict mode
like discussed in the v0.4 discussion? Like this here from the "Reviving
scalar type hints" thread?
I believe that RFCs should be opinionated. I dislike the recent trend
around having a lot of voting options as it only complicates things
for the voter.
For this reason I have chosen what I think is technically the best
option and went from there. I am definitely open to changing that, but
it would need to be based on technical reasons and not just "popular
preference". Heck, in a recent public poll, over 20% of respondents
voted for it being an ini setting.
I touched on the reasons in the RFC:
https://wiki.php.net/rfc/scalar_type_hints_v5#why_not_use_use_strict_instead_of_declare
But let me go through them one-by-one:
Am 17.02.2015 um 00:58 schrieb Sara Golemon:> Straw poll:
- <?php strict;
This is new syntax, which is potentially ambiguous around what
"strictness" is being applied. It limits future compatibility.
Additionally, it's potentially ambiguous if a file starts with <?=
strict; 4; ?>. Is that setting strict mode for a file and outputting
4? Or is it outputting the constant "strict"? Sure, this could be
"solved" with a rule that it could only follow <?php, but that starts
to get arbitrary and potentially confusing, given the other ways to
open PHP tags.
- <?php-strict
STRONG -1, as it leaves potential for code disclosure if run on a
earlier version of PHP.
- use strict; (psuedo-namespace)
Re-using namespaces to effect runtime is weird. Not to mention what's
the expected behavior of block mode:
<?php
namespace Foo {
use strict;
}
namespace {
bar();
}
?>
is bar() called in strict mode? Or in non-strict mode?
- <?php // strict (I don't actually like HHVM's style, but if you do...)
Comments should not affect runtime behavior. HHVM uses it as they need
to affect behavior while remaining compatible with PHP. We do not have
that problem.
- declare(strict=true); (As a top-level declare only)
- declare(strict=true); (exactly as in v0.3 -- maybe you liked it)
Which had a number of people against it, with arguments about the odd
behavior of declare in blocks, etc.
- your write-in vote here
The only other one I've seen that might make sense is using a strict
qualifier on the namespace declaration:
strict namespace Foo {
}
IMO this has the same issues as use strict above. However, it also
seems to imply that the namespace is strict, where it's only the
declarations in the file that are.
I'm 100% open to technical arguments and justification to switch to
another syntax. I don't believe that it should be a poll though.
That's why I made a decision and backed it up. If anyone has logical
arguments or disagrees, let's discuss it. That way the proposal can be
improved through collaboration rather than just a blind vote.
Thanks for the feedback!!!
Anthony
Hello Anthony,
Am 19.02.2015 um 14:01 schrieb Anthony Ferrara:
I believe that RFCs should be opinionated. I dislike the recent trend
around having a lot of voting options as it only complicates things
for the voter.
I just thought giving a vote on how to enable strict mode would enable a
few more people to actually vote yes. I myself can not vote but I really
hope we get scalar type hints in what kind soever into PHP 7. So keep on
and thank you for taking over.
Greets
Dennis
Hey Anthony,
-----Ursprüngliche Nachricht-----
Von: Anthony Ferrara [mailto:ircmaxell@gmail.com]
Gesendet: Mittwoch, 18. Februar 2015 21:45
An: internals@lists.php.net
Betreff: [PHP-DEV] [RFC-Discuss] Scalar Type Declarations v0.5Dear Internals,
Since the resignation of Andrea, the mixed-mode type hint (called declaration in the proposal) proposal has been left
abandoned.
Considering that the ending votes were 67/34 (66.3%) with several no-votes being only due to reasonably minor issues with
the proposal, I would like to re-propose her RFC with three minor modifications:
- declare(strict_types=1) (if used) is required to be the first instruction in the file only. No other usages allowed.
- declare(strict_types=1) {} (block mode) is specifically disallowed.
- int typed variables can resolve a parameter type of float So calling requiresAFloat(10) will work even in strict mode.
As this topic has and is being discussed to death, I have put a very large "discussion points" section:
https://wiki.php.net/rfc/scalar_type_hints_v5#discussion_pointsI would kindly ask, before replying that you check to see if your question is answered in that list.
If it is not, please follow up here and I will update the RFC.
If your question is listed and you feel that it wasn't given proper due, please let's discuss that.
https://wiki.php.net/rfc/scalar_type_hints_v5
Considering this proposal is a minor tweak on an already-discussed and voted-on proposal, I plan on bringing this RFC to
vote 1 week from today (on February 25th, 2015).Thanks,
Anthony
--
I have some questions:
you wrote: "aliases are removed (integer and boolean)"
what about the aliases real and double?
You wrote: "behaviour of weak type checks: float -> int *Only non-NaN floats between PHP_INT_MIN
and PHP_INT_MAX
accepted. (New in PHP 7, see the ZPP Failure on Overflow RFC)"
What about INF? Can INF
be passed or not and if so, how is it converted?
Personally I would be stricter and disallow int->bool, float->bool, string->bool as well as bool -> int, bool -> float and bool -> string (at least for this RFC)
Why?
- I already mentioned the common if(strpos(..)){} case but is something which none of the RFC addressed so far and probably goes too far (you wrote "In addition to userland functions, the strict type checking mode also affects extension and built-in PHP functions:" but control structures are not affected, right?)
- It supports an inconsistency in PHP which we should try to get away with rather than promoting it. Following an example:
function foo(string $x){
var_dump($x);
bar($x);
}
function bar(bool $x){
var_dump($x);
baz($x);
}
function baz(string $x){
var_dump($x);}
foo(0);
and the output would be:
string(1) "0"
bool(false)
string(0) ""
Sure, removing the implicit conversions from and to bool do not pretend that the same would happen if one uses manual conversions instead. Yet, IMO we should forbid the implicit conversion from and to bool now and add it later on with consistent conversion rules. This way we have more time to think about a clean solution and adding implicit conversion from and to bool should also not be a BC break in 7.1
Another example:
function foo(int $x){
var_dump($x);
bar($x);
}
function bar(string $x){
var_dump($x);
}
foo(false);
bar(false);
and output:
int(0)
string(1) "0"
string(0) ""
I think you get the inconsistency I am writing about.
About widening. It is not clear from the RFC if widening is only applied for int -> float or also for bool -> int, bool -> float respectively.
Cheers,
Robert
Robert,
you wrote: "aliases are removed (integer and boolean)"
what about the aliases real and double?
They were never part of Andrea's proposal. So they were never accepted anyway.
You wrote: "behaviour of weak type checks: float -> int *Only non-NaN floats between
PHP_INT_MIN
andPHP_INT_MAX
accepted. (New in PHP 7, see the ZPP Failure on Overflow RFC)"
What about INF? CanINF
be passed or not and if so, how is it converted?
Please see the other RFC: https://wiki.php.net/rfc/zpp_fail_on_overflow
Namely: The special floating-point values INF
and -INF fail the check
like any other number that is too large.
Personally I would be stricter and disallow int->bool, float->bool, string->bool as well as bool -> int, bool -> float and bool -> string (at least for this RFC)
Why?
- I already mentioned the common if(strpos(..)){} case but is something which none of the RFC addressed so far and probably goes too far (you wrote "In addition to userland functions, the strict type checking mode also affects extension and built-in PHP functions:" but control structures are not affected, right?)
This only affects function calls. Not control structures.
- It supports an inconsistency in PHP which we should try to get away with rather than promoting it. Following an example:
function foo(string $x){
var_dump($x);
bar($x);
}
function bar(bool $x){
var_dump($x);
baz($x);
}
function baz(string $x){
var_dump($x);}
foo(0);and the output would be:
string(1) "0"
bool(false)
string(0) ""Sure, removing the implicit conversions from and to bool do not pretend that the same would happen if one uses manual conversions instead. Yet, IMO we should forbid the implicit conversion from and to bool now and add it later on with consistent conversion rules. This way we have more time to think about a clean solution and adding implicit conversion from and to bool should also not be a BC break in 7.1
Simple: don't use weak mode. This proposal does not invent the weak
mode rules, it simply exposes them from ZPP (how it's implemented in
all internal functions) to userland hints.
So any change there would be outside of scope for this proposal and
should be made as another proposal. I will add this to the discussion
points section.
Another example:
function foo(int $x){
var_dump($x);
bar($x);
}
function bar(string $x){
var_dump($x);
}
foo(false);
bar(false);and output:
int(0)
string(1) "0"
string(0) ""I think you get the inconsistency I am writing about.
About widening. It is not clear from the RFC if widening is only applied for int -> float or also for bool -> int, bool -> float respectively.
It's explicitly stated: "This means that parameters that declare float
can also accept int."
I will clarify this as well.
Thanks!
Anthony
All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904
Namely that generated file caches may need the ability to switch block
mode on-and-off.
I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:
<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}
Having trailing code or code outside of the declare would be a compile error.
<?php
declare(strict_types=1) {
//...
}
foo(); // compile error
This behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).
I'm considering adding it, as it's a valid use-case. What do you think?
Thanks
Anthony
Dear Internals,
Since the resignation of Andrea, the mixed-mode type hint (called
declaration in the proposal) proposal has been left abandoned.
Considering that the ending votes were 67/34 (66.3%) with several
no-votes being only due to reasonably minor issues with the proposal,
I would like to re-propose her RFC with three minor modifications:
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed.- declare(strict_types=1) {} (block mode) is specifically disallowed.
- int typed variables can resolve a parameter type of float So
calling requiresAFloat(10) will work even in strict mode.As this topic has and is being discussed to death, I have put a very
large "discussion points" section:
https://wiki.php.net/rfc/scalar_type_hints_v5#discussion_pointsI would kindly ask, before replying that you check to see if your
question is answered in that list.If it is not, please follow up here and I will update the RFC.
If your question is listed and you feel that it wasn't given proper
due, please let's discuss that.https://wiki.php.net/rfc/scalar_type_hints_v5
Considering this proposal is a minor tweak on an already-discussed and
voted-on proposal, I plan on bringing this RFC to vote 1 week from
today (on February 25th, 2015).Thanks,
Anthony
All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a compile error.
<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).I'm considering adding it, as it's a valid use-case. What do you think?
Seems a valid use case, and the block solution is therefore the
logical step. I see no reason to exclude it.
Paddy
--
Pádraic Brady
http://blog.astrumfutura.com
http://www.survivethedeepend.com
All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a compile error.
<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).I'm considering adding it, as it's a valid use-case. What do you think?
So, I ran into a snag while doing this.
It turns out that in the parser implementation of declare is not going
to allow it without significant restructuring (including a lot of
validation in the compiler):
declare_statement:
statement { $$ = $1; }
| ':' inner_statement_list T_ENDDECLARE
';' { $$ = $2; }
;
So in block mode, declare supports inline, block and named-block mode:
declare(...) foo();
declare(...) {
foo();
}
declare(...):
foo();
enddeclare;
The problem with this is that namespace declarations can only happen
in top_statement (along with some other statements).
That leaves two options to support multiple modes per file:
- Allow in top-level only:
declare(strict_types=1);
namespace Foo {
}
declare(strict_types=0);
namespace Bar {
}
- inside of the namespace:
namespace Foo {
declare(strict_types=1);
}
namespace Bar {
}
The problem with the first is clarity (it's easy to miss a declare and
not understand that the mode has changed). We pinned declare to the
top of the file for clarity. I'm not sure this use-case is worth
breaking that clarity.
The problem with the second is more subtle. With the current
parser+compiler, that declare would affect the entire file. It would
take pretty significant changes and restructuring of the parser to
effect.
We could drop declare() all together and go with something like a
namespace modifier:
strict namespace Foo {
}
namespace Bar {
}
But I don't think it's worth it to conflate those two together. Though
if we did, the syntax "strict namespace;" would be supported for
non-namespaced strict code.
So in the end, my conclusion is that while it would be nice to support
the "compiled file" use-case fully, it's not worth it from a technical
level (the risk and degree of change required doesn't offset the
benefit of it).
So the proposal will remain unchainged and not support the block
syntax (or changing the mode mid-file).
Thanks
Anthony
All,
I have updated the RFC to re-target 7.0.
I have also added a new behavior:
Currently, if you install an error handler that returns true, you can
bypass type checking in userland functions.
set_error_handler(function() { return true; });
function foo(int $abc) {
var_dump($abc);
}
foo("test"); // string(4) "test"
This is obviously a problem for strict typing. Therefore, I am
proposing that strict mode bypass function execution in this case.
The current proposal for engine exceptions would eliminate the need
for this behavior. Therefore I documented the behavior, but am holding
off on the implementation until the engine exceptions vote concludes
(if it fails, the behavior documented in the RFC would be
implemented).
Thanks
Anthony
All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a compile error.
<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).I'm considering adding it, as it's a valid use-case. What do you think?
So, I ran into a snag while doing this.
It turns out that in the parser implementation of declare is not going
to allow it without significant restructuring (including a lot of
validation in the compiler):declare_statement:
statement { $$ = $1; }
| ':' inner_statement_listT_ENDDECLARE
';' { $$ = $2; }
;So in block mode, declare supports inline, block and named-block mode:
declare(...) foo();
declare(...) {
foo();
}
declare(...):
foo();
enddeclare;The problem with this is that namespace declarations can only happen
in top_statement (along with some other statements).That leaves two options to support multiple modes per file:
- Allow in top-level only:
declare(strict_types=1);
namespace Foo {
}
declare(strict_types=0);
namespace Bar {
}
- inside of the namespace:
namespace Foo {
declare(strict_types=1);
}
namespace Bar {
}The problem with the first is clarity (it's easy to miss a declare and
not understand that the mode has changed). We pinned declare to the
top of the file for clarity. I'm not sure this use-case is worth
breaking that clarity.The problem with the second is more subtle. With the current
parser+compiler, that declare would affect the entire file. It would
take pretty significant changes and restructuring of the parser to
effect.We could drop declare() all together and go with something like a
namespace modifier:strict namespace Foo {
}
namespace Bar {
}But I don't think it's worth it to conflate those two together. Though
if we did, the syntax "strict namespace;" would be supported for
non-namespaced strict code.So in the end, my conclusion is that while it would be nice to support
the "compiled file" use-case fully, it's not worth it from a technical
level (the risk and degree of change required doesn't offset the
benefit of it).So the proposal will remain unchainged and not support the block
syntax (or changing the mode mid-file).Thanks
Anthony
I've been having a play around with the implementation, and it's been
behaving pretty solidly, nothing unexpected so far.
I've even gotten around my issue regarding no strict-by-default option
for those of us who want it.
Maybe this will sway a few voters. I'll put the source up if this
particular implementation gets through (no point otherwise!)
~/php-strict $ ../php-src/sapi/cli/php -r 'function foo(int $bar) {
var_dump($bar); } foo("10");'
int(10)
~/php-strict $ ../php-src/sapi/cli/php -d extension=modules/strict.so
-r 'function foo(int $bar) { var_dump($bar); } foo("10");'
Catchable fatal error: Argument 1 passed to foo() must be of the type
integer, string given, called in Command line code on line 1 and
defined in Command line code on line 1
Hi Anthony,
Few notes:
-
first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type hinting
as you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way, because
in each function we will have to handle both options
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR3762
and also set additional flag on each call
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR2802
. -
resource type hint may be useful in the same way as all other types
-
it may make sense not to disable bool/int/float/string classes at all. we
may just don't allow them in type hints. This will break less applications.
Thanks. Dmitry.
On Sat, Feb 21, 2015 at 6:35 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
All,
I have updated the RFC to re-target 7.0.
I have also added a new behavior:
Currently, if you install an error handler that returns true, you can
bypass type checking in userland functions.set_error_handler(function() { return true; });
function foo(int $abc) {
var_dump($abc);
}
foo("test"); // string(4) "test"This is obviously a problem for strict typing. Therefore, I am
proposing that strict mode bypass function execution in this case.The current proposal for engine exceptions would eliminate the need
for this behavior. Therefore I documented the behavior, but am holding
off on the implementation until the engine exceptions vote concludes
(if it fails, the behavior documented in the RFC would be
implemented).Thanks
Anthony
On Fri, Feb 20, 2015 at 4:09 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a compile
error.<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).I'm considering adding it, as it's a valid use-case. What do you think?
So, I ran into a snag while doing this.
It turns out that in the parser implementation of declare is not going
to allow it without significant restructuring (including a lot of
validation in the compiler):declare_statement:
statement { $$ = $1; }
| ':' inner_statement_listT_ENDDECLARE
';' { $$ = $2; }
;So in block mode, declare supports inline, block and named-block mode:
declare(...) foo();
declare(...) {
foo();
}
declare(...):
foo();
enddeclare;The problem with this is that namespace declarations can only happen
in top_statement (along with some other statements).That leaves two options to support multiple modes per file:
- Allow in top-level only:
declare(strict_types=1);
namespace Foo {
}
declare(strict_types=0);
namespace Bar {
}
- inside of the namespace:
namespace Foo {
declare(strict_types=1);
}
namespace Bar {
}The problem with the first is clarity (it's easy to miss a declare and
not understand that the mode has changed). We pinned declare to the
top of the file for clarity. I'm not sure this use-case is worth
breaking that clarity.The problem with the second is more subtle. With the current
parser+compiler, that declare would affect the entire file. It would
take pretty significant changes and restructuring of the parser to
effect.We could drop declare() all together and go with something like a
namespace modifier:strict namespace Foo {
}
namespace Bar {
}But I don't think it's worth it to conflate those two together. Though
if we did, the syntax "strict namespace;" would be supported for
non-namespaced strict code.So in the end, my conclusion is that while it would be nice to support
the "compiled file" use-case fully, it's not worth it from a technical
level (the risk and degree of change required doesn't offset the
benefit of it).So the proposal will remain unchainged and not support the block
syntax (or changing the mode mid-file).Thanks
Anthony
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>
a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>
b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>
Thank. Dmitry.
Hi Anthony,
Few notes:
first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type hinting
as you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way, because
in each function we will have to handle both options
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR3762
and also set additional flag on each call
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR2802
.resource type hint may be useful in the same way as all other types
it may make sense not to disable bool/int/float/string classes at all.
we may just don't allow them in type hints. This will break less
applications.Thanks. Dmitry.
On Sat, Feb 21, 2015 at 6:35 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:All,
I have updated the RFC to re-target 7.0.
I have also added a new behavior:
Currently, if you install an error handler that returns true, you can
bypass type checking in userland functions.set_error_handler(function() { return true; });
function foo(int $abc) {
var_dump($abc);
}
foo("test"); // string(4) "test"This is obviously a problem for strict typing. Therefore, I am
proposing that strict mode bypass function execution in this case.The current proposal for engine exceptions would eliminate the need
for this behavior. Therefore I documented the behavior, but am holding
off on the implementation until the engine exceptions vote concludes
(if it fails, the behavior documented in the RFC would be
implemented).Thanks
Anthony
On Fri, Feb 20, 2015 at 4:09 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a compile
error.<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the namespace
block).I'm considering adding it, as it's a valid use-case. What do you think?
So, I ran into a snag while doing this.
It turns out that in the parser implementation of declare is not going
to allow it without significant restructuring (including a lot of
validation in the compiler):declare_statement:
statement { $$ = $1; }
| ':' inner_statement_listT_ENDDECLARE
';' { $$ = $2; }
;So in block mode, declare supports inline, block and named-block mode:
declare(...) foo();
declare(...) {
foo();
}
declare(...):
foo();
enddeclare;The problem with this is that namespace declarations can only happen
in top_statement (along with some other statements).That leaves two options to support multiple modes per file:
- Allow in top-level only:
declare(strict_types=1);
namespace Foo {
}
declare(strict_types=0);
namespace Bar {
}
- inside of the namespace:
namespace Foo {
declare(strict_types=1);
}
namespace Bar {
}The problem with the first is clarity (it's easy to miss a declare and
not understand that the mode has changed). We pinned declare to the
top of the file for clarity. I'm not sure this use-case is worth
breaking that clarity.The problem with the second is more subtle. With the current
parser+compiler, that declare would affect the entire file. It would
take pretty significant changes and restructuring of the parser to
effect.We could drop declare() all together and go with something like a
namespace modifier:strict namespace Foo {
}
namespace Bar {
}But I don't think it's worth it to conflate those two together. Though
if we did, the syntax "strict namespace;" would be supported for
non-namespaced strict code.So in the end, my conclusion is that while it would be nice to support
the "compiled file" use-case fully, it's not worth it from a technical
level (the risk and degree of change required doesn't offset the
benefit of it).So the proposal will remain unchainged and not support the block
syntax (or changing the mode mid-file).Thanks
Anthony
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of foo
will be coerced to
int type when passed to bar by reference.
References are a problem for weak-only types as well (even more so I would
say, because in a lot of cases they would continue working truncated or
changed).
Happily there are not lots of post-php5 code that uses references here and
there, but that would be good to add the point about them to both RFCs
(and in documentation in future) just so that users would be aware of that.
On Wed, 25 Feb 2015 15:42:11 +0400, Niktia Nefedov inefedor@gmail.com
wrote:
On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.References are a problem for weak-only types as well (even more so I
would say, because in a lot of cases they would continue working
truncated or changed).Happily there are not lots of post-php5 code that uses references here
and there, but that would be good to add the point about them to both
RFCs (and in documentation in future) just so that users would be aware
of that.
Ah sorry I was too quick on judging, Florian is right, when foo returns
its value it will be coerced back to string because of strict=0 in this
case...
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.
I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet.
Thanks. Dmitry.
References are a problem for weak-only types as well (even more so I would
say, because in a lot of cases they would continue working truncated or
changed).Happily there are not lots of post-php5 code that uses references here and
there, but that would be good to add the point about them to both RFCs (and
in documentation in future) just so that users would be aware of that.
On Wed, Feb 25, 2015 at 2:42 PM, Niktia Nefedov inefedor@gmail.com
wrote:On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet.
Yep, you're right. But it's not a problem of mixed-mode, it's more of a
problem of introducing coercive type hints at all, honestly... I wonder
what Zeev plans to do with __toString coercion in his RFC, because that is
even more severe problem when your object unnoticedly becomes a string.
On Wed, 25 Feb 2015 16:55:57 +0400, Dmitry Stogov dmitry@zend.com
wrote:On Wed, Feb 25, 2015 at 2:42 PM, Niktia Nefedov inefedor@gmail.com
wrote:On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet.Yep, you're right. But it's not a problem of mixed-mode, it's more of a
problem of introducing coercive type hints at all, honestly... I wonder
what Zeev plans to do with __toString coercion in his RFC, because that is
even more severe problem when your object unnoticedly becomes a string.
The object on the call-site should remain to be an object (if it's not
passed by reference), however the called function will receive a string.
It works in PHP-5 and PHP-7. Nothing should be changed.
$ sapi/cli/php -r 'class X {function __toString(){return "abc";}} $x=new X;
var_dump(strlen($x)); var_dump($x);'
int(3)
object(X)#1 (0) {
}
However, declare(strict_types=1) will break this. see
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-ef5bf53d1412b50f85d125ca4fe84741R1182
Thanks. Dmitry.
Dmitry,
The object on the call-site should remain to be an object (if it's not
passed by reference), however the called function will receive a string.
It works in PHP-5 and PHP-7. Nothing should be changed.$ sapi/cli/php -r 'class X {function __toString(){return "abc";}} $x=new X;
var_dump(strlen($x)); var_dump($x);'
int(3)
object(X)#1 (0) {
}However, declare(strict_types=1) will break this. see
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-ef5bf53d1412b50f85d125ca4fe84741R1182
"Break" is a loaded term.
It's intentionally not calling __toString, because that's not only a
cast (like "5" -> int(5)), but it's a lossy cast (like 5.5 -> int(5)
or "5 apples" => int(5)).
One point of strict mode is that it's there intentionally to turn off
magic. It's there to make things explicit, predictable and robust.
And it's fully opt-in, so there's nothing to "break". It's entirely
new behavior.
Anthony
On Wed, Feb 25, 2015 at 6:09 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry,
The object on the call-site should remain to be an object (if it's not
passed by reference), however the called function will receive a string.
It works in PHP-5 and PHP-7. Nothing should be changed.$ sapi/cli/php -r 'class X {function __toString(){return "abc";}} $x=new
X;
var_dump(strlen($x)); var_dump($x);'
int(3)
object(X)#1 (0) {
}However, declare(strict_types=1) will break this. see
"Break" is a loaded term.
OK. it's a BC break.
What is the reason for __toString() if it's not going to be called.
It's intentionally not calling __toString, because that's not only a
cast (like "5" -> int(5)), but it's a lossy cast (like 5.5 -> int(5)
or "5 apples" => int(5)).
this is about conversion rules that may be safe or not.
One point of strict mode is that it's there intentionally to turn off
magic. It's there to make things explicit, predictable and robust.
turn off magic to get what? Need to write explicit (int) or (string)?
We have a number of such patterns that hide errors even in PHP sources (in
C).
Thanks. Dmitry.
And it's fully opt-in, so there's nothing to "break". It's entirely
new behavior.
Anthony
On Wed, Feb 25, 2015 at 6:09 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:Dmitry,
The object on the call-site should remain to be an object (if it's not
passed by reference), however the called function will receive a string.
It works in PHP-5 and PHP-7. Nothing should be changed.$ sapi/cli/php -r 'class X {function __toString(){return "abc";}} $x=new
X;
var_dump(strlen($x)); var_dump($x);'
int(3)
object(X)#1 (0) {
}However, declare(strict_types=1) will break this. see
"Break" is a loaded term.
OK. it's a BC break.
What is the reason for __toString() if it's not going to be called.It's intentionally not calling __toString, because that's not only a
cast (like "5" -> int(5)), but it's a lossy cast (like 5.5 -> int(5)
or "5 apples" => int(5)).this is about conversion rules that may be safe or not.
One point of strict mode is that it's there intentionally to turn off
magic. It's there to make things explicit, predictable and robust.turn off magic to get what? Need to write explicit (int) or (string)?
We have a number of such patterns that hide errors even in PHP sources (in
C).
Right, we do. And we should somehow treat warnings like that as error, in C :)
That being said (and totally OT), changing casting rules and adding
yet another set of magic rules is better? I agree to totally disagree
here. I will never agree on changing these rules (or maybe in php12).
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
Dmitry:
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet.
"Weird"?
int(5)
string(1) "5"
How is that weird? That's precisely what you asked it to do.
On Wed, Feb 25, 2015 at 6:06 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry:
On Wed, Feb 25, 2015 at 2:42 PM, Niktia Nefedov inefedor@gmail.com
wrote:On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet."Weird"?
int(5)
string(1) "5"How is that weird? That's precisely what you asked it to do.
I just think that not allbody understand this and expect something
different.
Thanks. Dmitry.
Dmitry
On Wed, Feb 25, 2015 at 6:06 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:Dmitry:
On Wed, Feb 25, 2015 at 2:42 PM, Niktia Nefedov inefedor@gmail.com
wrote:On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but weird
output. I didn't run it myself yet."Weird"?
int(5)
string(1) "5"How is that weird? That's precisely what you asked it to do.
I just think that not allbody understand this and expect something
different.
Looking at that code, even not knowing this RFC and the details of the
implementation, what would you expect to be different about it?
Now, having read the RFC and played with the patch (even though you
admitted that you didn't), what would you expect to be different?
Anthony
On Wed, Feb 25, 2015 at 6:24 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry
On Wed, Feb 25, 2015 at 6:06 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:Dmitry:
On Wed, Feb 25, 2015 at 2:42 PM, Niktia Nefedov inefedor@gmail.com
wrote:On Wed, 25 Feb 2015 16:30:32 +0400, Dmitry Stogov dmitry@zend.com
wrote:anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
Hi Dmitry,
This will error out because $a in the scope of
foo
will be coerced
to
int type when passed to bar by reference.I think it'll work without errors and produce some explainable but
weird
output. I didn't run it myself yet."Weird"?
int(5)
string(1) "5"How is that weird? That's precisely what you asked it to do.
I just think that not allbody understand this and expect something
different.Looking at that code, even not knowing this RFC and the details of the
implementation, what would you expect to be different about it?
I expected the same, especially because I read the code.
Now, having read the RFC and played with the patch (even though you
admitted that you didn't), what would you expect to be different?
You already saw, at least one who was in time to make mistake.
I was expecting this :)
Thanks. Dmitry.
Anthony
Hi,
Le 25 févr. 2015 13:31, "Dmitry Stogov" dmitry@zend.com a écrit :
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>
No error. The declare is per-file.
Thank. Dmitry.
Hi Anthony,
Few notes:
- first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type
hinting
as you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way,
because
in each function we will have to handle both options
and also set additional flag on each call
.
resource type hint may be useful in the same way as all other types
it may make sense not to disable bool/int/float/string classes at all.
we may just don't allow them in type hints. This will break less
applications.Thanks. Dmitry.
On Sat, Feb 21, 2015 at 6:35 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:All,
I have updated the RFC to re-target 7.0.
I have also added a new behavior:
Currently, if you install an error handler that returns true, you can
bypass type checking in userland functions.set_error_handler(function() { return true; });
function foo(int $abc) {
var_dump($abc);
}
foo("test"); // string(4) "test"This is obviously a problem for strict typing. Therefore, I am
proposing that strict mode bypass function execution in this case.The current proposal for engine exceptions would eliminate the need
for this behavior. Therefore I documented the behavior, but am holding
off on the implementation until the engine exceptions vote concludes
(if it fails, the behavior documented in the RFC would be
implemented).Thanks
Anthony
On Fri, Feb 20, 2015 at 4:09 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:All,
An interesting point was brought up related to block mode:
https://twitter.com/drrotmos/status/568540722586107904Namely that generated file caches may need the ability to switch
block
mode on-and-off.I'm considering making the change to add that. If that happens,
declare must be the outermost block, and no non-declare blocks would
be allowed in the outermost scope of the file:<?php
declare(strict_types=1) {
//...
}
declare(strict_types=0) {
//...
}Having trailing code or code outside of the declare would be a
compile
error.<?php
declare(strict_types=1) {
//...
}
foo(); // compile errorThis behaves consistent with namespace block-mode today (though the
strict type declaration would be required to be outside the
namespace
block).I'm considering adding it, as it's a valid use-case. What do you
think?So, I ran into a snag while doing this.
It turns out that in the parser implementation of declare is not
going
to allow it without significant restructuring (including a lot of
validation in the compiler):declare_statement:
statement { $$ = $1; }
| ':' inner_statement_listT_ENDDECLARE
';' { $$ = $2; }
;So in block mode, declare supports inline, block and named-block
mode:declare(...) foo();
declare(...) {
foo();
}
declare(...):
foo();
enddeclare;The problem with this is that namespace declarations can only happen
in top_statement (along with some other statements).That leaves two options to support multiple modes per file:
- Allow in top-level only:
declare(strict_types=1);
namespace Foo {
}
declare(strict_types=0);
namespace Bar {
}
- inside of the namespace:
namespace Foo {
declare(strict_types=1);
}
namespace Bar {
}The problem with the first is clarity (it's easy to miss a declare
and
not understand that the mode has changed). We pinned declare to the
top of the file for clarity. I'm not sure this use-case is worth
breaking that clarity.The problem with the second is more subtle. With the current
parser+compiler, that declare would affect the entire file. It would
take pretty significant changes and restructuring of the parser to
effect.We could drop declare() all together and go with something like a
namespace modifier:strict namespace Foo {
}
namespace Bar {
}But I don't think it's worth it to conflate those two together.
Though
if we did, the syntax "strict namespace;" would be supported for
non-namespaced strict code.So in the end, my conclusion is that while it would be nice to
support
the "compiled file" use-case fully, it's not worth it from a
technical
level (the risk and degree of change required doesn't offset the
benefit of it).So the proposal will remain unchainged and not support the block
syntax (or changing the mode mid-file).Thanks
Anthony
--
Cheers,
Florian Margaine
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
As I understand the proposal and above example, it's possible to change the
'strict_type' settings per file.
So, for an enterprise application being developed over many years, it's a
very realistic scenario
that this setting will be different in different files especially if coding
conventions are not followed (happens very often).
Does that mean when reading or writing code, in addition to checking the
signature of a function,
I have to check the 'strict_types' setting at the top as well, to
understand how that signature behaves?
Thanks
Shashank
On Wed, Feb 25, 2015 at 3:54 PM, Shashank Kumar shashankkumar.me@gmail.com
wrote:
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>Thank. Dmitry.
As I understand the proposal and above example, it's possible to change
the 'strict_type' settings per file.
So, for an enterprise application being developed over many years, it's a
very realistic scenario
that this setting will be different in different files especially if
coding conventions are not followed (happens very often).Does that mean when reading or writing code, in addition to checking the
signature of a function,
I have to check the 'strict_types' setting at the top as well, to
understand how that signature behaves?
I think you should check it in the top line of the file where the function
was called from.
Thanks. Dmitry.
Thanks
Shashank
Does that mean when reading or writing code, in addition to checking the
signature of a function,
I have to check the 'strict_types' setting at the top as well, to
understand how that signature behaves?I think you should check it in the top line of the file where the function
was called from.
Of cause the real world situation here is that the legacy included files
and their functions will simply not have type hints. The problems only
start to arise if someone updates the library code following one
practice while other users are not even bothered by it. I get that if
strict typing is added to the library, but the user is not bothering
with any type hinting than it will not get in the way, but there still
has to be checks in the to find out if the strict check is needed while
I may well simply be using the library like I always have ... and
throwing strings at it. It's at this point I am trying to work out what
will happen? If I am a novice users I just expect the normal weak
conversion, and presumably the 'strict mode' function I am calling has
the code to cater for that in this instance while also having the checks
for strict mode ready for strict mode calls to the same function? I
don't see how any of this can be optimised out unless the code is only
compiled for one mode or the other.
One has to add of cause any third party change to the conversion rules
which may come into play as well, but I still see all of this as a red
herring since the reason any type hint fails is of more importance than
catching that the wrong type of value has arrived. MOST of the time this
is 'protecting' against morons who are only interested in hacking your
site, so while one passes a few integers via the URL handshaking to
control navigation perhaps, one has to ensure that when someone tries to
inject alternate text things fail tidily? Even if data is validated via
javascript in the browser one can't assume that what should be a nice
clean value is actually what gets through? All right if that fails in a
later function call then one can crash out, and you don't want to serve
hackers anyway, but one needs to know if it is a hacker or a user with a
problem. But this more a play against the need for type hinting at all ...
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
-----Original Message-----
From: Shashank Kumar [mailto:shashankkumar.me@gmail.com]
Sent: Wednesday, February 25, 2015 2:54 PM
To: Dmitry Stogov
Cc: Anthony Ferrara; internals@lists.php.net
Subject: Re: [PHP-DEV] Re: [RFC-Discuss] Scalar Type Declarations v0.5On Wed, Feb 25, 2015 at 4:30 AM, Dmitry Stogov dmitry@zend.com
wrote:As I understand the proposal and above example, it's possible to change
the
'strict_type' settings per file.
So, for an enterprise application being developed over many years, it's a
very
realistic scenario that this setting will be different in different files
especially
if coding conventions are not followed (happens very often).Does that mean when reading or writing code, in addition to checking the
signature of a function, I have to check the 'strict_types' setting at the
top as
well, to understand how that signature behaves?
Not quite; You need to check the strict_types setting not where the
function is defined, but where the function call is being made. It means
that if you're editing other people's code, you first need to check what
mode you're at, as it will determine the semantics of function calls in the
file you're editing.
Independent of the issues I see with strict types themselves, I think the
concept of a dual mode has two substantial disadvantages:
- It's an extra element to worry about when determining what your code will
behave like. Yes, it's self-contained in the file - which is an advantage
of INI entries, but it's still another thing to worry about. - As your question suggests, I think we have substantial evidence that the
nature of this dual mode will be confusing to users. And we're not talking
about the average users - we're talking about internals@ subscribers, some
of which are big community leaders (sorry Matthew :).
Combined, it's additional cognitive burden on the developer base, and it may
also be divisive (e.g. "I only use libraries written with strict mode" or
vice versa). That's why in the Coercive RFC we sought to find a combined
ruleset that does away with these disadvantages, while doing its best to
cater to the key needs of both camps, with the endgame being having just one
camp.
Zeev
anyone may tell, what this will print without running :)
main.php
<?php
declare(strict_types=1)
include "a.php";
include "b.php";
var_dump(foo("5"));
?>a.php
<?php
declare(strict_types=0)
function foo(string $a): string {
bar($a);
return $a;
}
?>b.php
<?php
declare(strict_types=1)
function bar(int &$a) {
var_dump($a);
}
?>
I am not sure if we really need to focus the discussion on whether edge
cases using references are confusing or not. They already are confusing
even without scalar hints (of any kind), and that's why most people know
to stay away from refs in PHP.
PHP5 would behave the same if you did an explicit $a = (int) $a; in
bar() for example, and the same WTF happens with the other RFC, so I am
not really sure what you are trying to point out here.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
Dmitry,
Hi Anthony,
Few notes:
- first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type hinting as
I've mentioned this a few times, but I disagree with that concept. I
believe RFCs should fully describe a feature and should be voted on in
whole.
Additionally, it presents a problem when it comes to voting. What if a
person wants strict types. And it looks like it's overall going to
pass, but that weak types is winning. What's the best way for them to
vote? No. For the entire proposal.
I'd rather keep the vote about one thing, and one thing only.
you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way, because in
each function we will have to handle both options
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR3762
and also set additional flag on each call
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR2802
What negative way is that? It's a clearly defined switch, kept in a
clearly defined place.
And considering it's a purely compile time construct, I fail to see
how it could possibly affect either the VM or JITed code in a negative
way.
Heck, if we really wanted to, we could compile a separate
ZEND_DO_FCALL opcode for strict types: ZEND_DO_STRICT_FCALL, which
hard-codes the strict data.
- resource type hint may be useful in the same way as all other types
The problem here is typing on a resource doesn't give you enough
information to be "safe":
function foo(resource $bar): string {
return fread($bar);
}
foo(mysql_connect(...));
I think a longer-term plan to replace (transparently) resources with
objects would be far more beneficial.
- it may make sense not to disable bool/int/float/string classes at all. we
may just don't allow them in type hints. This will break less applications.
It'll still break applications, because you can no longer do:
function foo(String $string) {}
foo(new String);
I think leaving the ability to create a class named "string" while at
the same time removing the ability to type against it is not only
weird, but definitely not something I think we should do (it's just
way to inconsistent).
Anthony
On Wed, Feb 25, 2015 at 6:03 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry,
Hi Anthony,
Few notes:
- first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type
hinting asI've mentioned this a few times, but I disagree with that concept. I
believe RFCs should fully describe a feature and should be voted on in
whole.Additionally, it presents a problem when it comes to voting. What if a
person wants strict types. And it looks like it's overall going to
pass, but that weak types is winning. What's the best way for them to
vote? No. For the entire proposal.
It's also a reason why others may vote against the whole and we will get
nothing.
I'd rather keep the vote about one thing, and one thing only.
I got you. All or nothing :)
you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way,
because in
each function we will have to handle both optionsand also set additional flag on each call
What negative way is that? It's a clearly defined switch, kept in a
clearly defined place.And considering it's a purely compile time construct, I fail to see
how it could possibly affect either the VM or JITed code in a negative
way.
I post the links to the important changes above. Even JITed code will have
to implement these additional checks in run-time.
Heck, if we really wanted to, we could compile a separate
ZEND_DO_FCALL opcode for strict types: ZEND_DO_STRICT_FCALL, which
hard-codes the strict data.
It's not so simple, because you don't know the function at compile-time.
- resource type hint may be useful in the same way as all other types
The problem here is typing on a resource doesn't give you enough
information to be "safe":function foo(resource $bar): string {
return fread($bar);
}foo(mysql_connect(...));
I think a longer-term plan to replace (transparently) resources with
objects would be far more beneficial.
Not all resources may be replaced with objects.
- it may make sense not to disable bool/int/float/string classes at all.
we
may just don't allow them in type hints. This will break less
applications.It'll still break applications, because you can no longer do:
function foo(String $string) {}
foo(new String);
right. but this is a smaller break.
I think leaving the ability to create a class named "string" while at
the same time removing the ability to type against it is not only
weird, but definitely not something I think we should do (it's just
way to inconsistent).
this is your opinion. I have another. I don't know opinion of others.
Why not to 50/50 voting. If you don't do it, may be I should do.
Thanks. Dmitry.
Anthony
Dmitry,
On Wed, Feb 25, 2015 at 6:03 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:Dmitry,
Hi Anthony,
Few notes:
- first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type
hinting asI've mentioned this a few times, but I disagree with that concept. I
believe RFCs should fully describe a feature and should be voted on in
whole.Additionally, it presents a problem when it comes to voting. What if a
person wants strict types. And it looks like it's overall going to
pass, but that weak types is winning. What's the best way for them to
vote? No. For the entire proposal.It's also a reason why others may vote against the whole and we will get
nothing.I'd rather keep the vote about one thing, and one thing only.
I got you. All or nothing :)
Yes. Because you, Zeev and Francois are making a competing proposal.
Which is the better way to decide, since then people can vote
independently for a specific implementation, not a complex set of
switches.
So if both fail, then we don't see scalar type declarations. If one
passes, we know what people want. If both pass, then we deal with that
then.
I even agreed to postpone the vote on this proposal so you could
finish yours. So please stop trying to spread FUD here and play both
sides of the game.
you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way,
because in
each function we will have to handle both optionshttps://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-3054389ad750ce9a9f5895cd6d27800fR3762
and also set additional flag on each callWhat negative way is that? It's a clearly defined switch, kept in a
clearly defined place.And considering it's a purely compile time construct, I fail to see
how it could possibly affect either the VM or JITed code in a negative
way.I post the links to the important changes above. Even JITed code will have
to implement these additional checks in run-time.
The call is compiled at compile time. The call's strict mode is
decided at compile time. So while the actual type checks happen at
runtime, and the function binding happens at runtime, the actual
switch happens at compile time.
Heck, if we really wanted to, we could compile a separate
ZEND_DO_FCALL opcode for strict types: ZEND_DO_STRICT_FCALL, which
hard-codes the strict data.It's not so simple, because you don't know the function at compile-time.
You don't need to know the destination function to determine if it's
going to be strict mode or not.
I think leaving the ability to create a class named "string" while at
the same time removing the ability to type against it is not only
weird, but definitely not something I think we should do (it's just
way to inconsistent).this is your opinion. I have another. I don't know opinion of others.
Why not to 50/50 voting. If you don't do it, may be I should do.
I said it was my opinion.
I also will not put it up to vote, because the proposal is a
codification of my views for the way forward. I said I'd be open to
discussing anything in the proposal. But ultimately it's a single
proposal, not a menu of choices. Please stop asking me to add
individual votes for every little detail. The only thing that
accomplishes is making it infinitely harder for people to understand
what they are voting on. Right now, it's an "all or nothing" vote.
Which means that it's very easy for people to understand what they
will get if it passes.
"Break" is a loaded term.
OK. it's a BC break.
What is the reason for __toString() if it's not going to be called.
It's absolutely not a BC break by any definition of the term that
we've ever used here, nor in the community. It's 100% acceptable
with semver. Heck, even Wikipedia's definition is consistent:
http://en.wikipedia.org/wiki/Backward_compatibility
You have to specifically opt-in to strict mode. Meaning that unless we
make changes to the coercive mode, there is by definition no BC break.
I expect you'll vote against the proposal either way, which is fine.
But please stop spreading misinformation and using loaded terms
improperly.
As far as "what is the reason for __toString if it's not going to be
called" I explained it right below where you quoted:
It's intentionally not calling __toString, because that's not only a
cast (like "5" -> int(5)), but it's a lossy cast (like 5.5 -> int(5)
or "5 apples" => int(5)).
__toString will still work in weak mode for parameters, and you can
still echo out the string just fine. But if you accept an object that
implements __toString, you can't just pass it to strlen without
explicitly converting it to a string first. Just like numbers. Just
like all of the other conversions. Just like you can't pass a Foo
instance to something expecting a Bar instance without an adapter in
between.
It'd be quite weird to reject int(5) for string, while accepting new
FooHasToString();. So either we go full strict (hence the strict mode)
or we don't (hence the weak mode). Here, we're giving the author the
choice.
Anthony
On Wed, Feb 25, 2015 at 6:47 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry,
On Wed, Feb 25, 2015 at 6:03 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:Dmitry,
Hi Anthony,
Few notes:
- first of all, it would be great to split the voting questions: 2/3 -
implement scalar type hinting + 1/2 - in addition add strict type
hinting asI've mentioned this a few times, but I disagree with that concept. I
believe RFCs should fully describe a feature and should be voted on in
whole.Additionally, it presents a problem when it comes to voting. What if a
person wants strict types. And it looks like it's overall going to
pass, but that weak types is winning. What's the best way for them to
vote? No. For the entire proposal.It's also a reason why others may vote against the whole and we will get
nothing.I'd rather keep the vote about one thing, and one thing only.
I got you. All or nothing :)
Yes. Because you, Zeev and Francois are making a competing proposal.
Which is the better way to decide, since then people can vote
independently for a specific implementation, not a complex set of
switches.So if both fail, then we don't see scalar type declarations. If one
passes, we know what people want. If both pass, then we deal with that
then.I even agreed to postpone the vote on this proposal so you could
finish yours. So please stop trying to spread FUD here and play both
sides of the game.
OK. It's going to be the last email.
you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way,
because in
each function we will have to handle both optionsand also set additional flag on each call
What negative way is that? It's a clearly defined switch, kept in a
clearly defined place.And considering it's a purely compile time construct, I fail to see
how it could possibly affect either the VM or JITed code in a negative
way.I post the links to the important changes above. Even JITed code will
have
to implement these additional checks in run-time.The call is compiled at compile time. The call's strict mode is
decided at compile time. So while the actual type checks happen at
runtime, and the function binding happens at runtime, the actual
switch happens at compile time.
Even Java don't always know the method it's going to call at compile-time.
PHP doesn't know it for sure.
Heck, if we really wanted to, we could compile a separate
ZEND_DO_FCALL opcode for strict types: ZEND_DO_STRICT_FCALL, which
hard-codes the strict data.It's not so simple, because you don't know the function at compile-time.
You don't need to know the destination function to determine if it's
going to be strict mode or not.
But checks are performed not in the caller but in RECV opcode at called
function.
And in this function we don't know id it's going to be called only in
strict mode or in weak as well.
I think leaving the ability to create a class named "string" while at
the same time removing the ability to type against it is not only
weird, but definitely not something I think we should do (it's just
way to inconsistent).this is your opinion. I have another. I don't know opinion of others.
Why not to 50/50 voting. If you don't do it, may be I should do.I said it was my opinion.
I also will not put it up to vote, because the proposal is a
codification of my views for the way forward. I said I'd be open to
discussing anything in the proposal. But ultimately it's a single
proposal, not a menu of choices. Please stop asking me to add
individual votes for every little detail. The only thing that
accomplishes is making it infinitely harder for people to understand
what they are voting on. Right now, it's an "all or nothing" vote.
Which means that it's very easy for people to understand what they
will get if it passes.
Thanks. Dmitry.
"Break" is a loaded term.
OK. it's a BC break.
What is the reason for __toString() if it's not going to be called.It's absolutely not a BC break by any definition of the term that
we've ever used here, nor in the community. It's 100% acceptable
with semver. Heck, even Wikipedia's definition is consistent:
http://en.wikipedia.org/wiki/Backward_compatibilityYou have to specifically opt-in to strict mode. Meaning that unless we
make changes to the coercive mode, there is by definition no BC break.I expect you'll vote against the proposal either way, which is fine.
But please stop spreading misinformation and using loaded terms
improperly.As far as "what is the reason for __toString if it's not going to be
called" I explained it right below where you quoted:It's intentionally not calling __toString, because that's not only a
cast (like "5" -> int(5)), but it's a lossy cast (like 5.5 -> int(5)
or "5 apples" => int(5)).__toString will still work in weak mode for parameters, and you can
still echo out the string just fine. But if you accept an object that
implements __toString, you can't just pass it to strlen without
explicitly converting it to a string first. Just like numbers. Just
like all of the other conversions. Just like you can't pass a Foo
instance to something expecting a Bar instance without an adapter in
between.It'd be quite weird to reject int(5) for string, while accepting new
FooHasToString();. So either we go full strict (hence the strict mode)
or we don't (hence the weak mode). Here, we're giving the author the
choice.Anthony
Dmitry,
But checks are performed not in the caller but in RECV opcode at called
function.
And in this function we don't know id it's going to be called only in strict
mode or in weak as well.
Currently, yes. However, by the time we enter ZEND_DO_FCALL, we know
which function we're going to call. And at compile time, we know how
many arguments exist.
We can also move the argument verification from RECV into
ZEND_DO_FCALL just like happens today with internal functions. In
fact, it may be worthwhile investigating that in general.
Anthony
On Wed, Feb 25, 2015 at 7:06 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Dmitry,
But checks are performed not in the caller but in RECV opcode at called
function.
And in this function we don't know id it's going to be called only in
strict
mode or in weak as well.Currently, yes. However, by the time we enter ZEND_DO_FCALL, we know
which function we're going to call. And at compile time, we know how
many arguments exist.We can also move the argument verification from RECV into
ZEND_DO_FCALL just like happens today with internal functions. In
fact, it may be worthwhile investigating that in general.
ZEND_DO_FCALL is a bad place. You'll have to traverse arguments and
arg_infos one more time.
It may make sense to add checks into ZEND_SEND_... opcodes.
This should be the cheapest option, however I'm not sure what kind of
impact and side effects it will make.
Also, even if we move checks into ZEND_SEND_..., we will have to keep
checks in ZEND_RECV anyway (for missing arguments).
This is not a big problem, because we will able to unconditionally skip
first RECV opocdes for passed arguments.
Thanks. Dmitry.
Anthony
De : Anthony Ferrara [mailto:ircmaxell@gmail.com]
Additionally, it presents a problem when it comes to voting. What if a
person wants strict types. And it looks like it's overall going to
pass, but that weak types is winning. What's the best way for them to
vote? No. For the entire proposal.
Agreed. IMO, splitting votes is theoretically possible, but not in parallel.
Actually, if we had wanted to proceed this way, we should already have finished the first vote. Too late now.
I don't know if it was already suggested but, whatever the date each STH vote starts, I suggest we synchronize end dates, in an attempt to limit side effects.
I don't know it the tool we use can be configured to allow for each user to see only his own vote before vote ends, and only global result when it is over, but it would probably improve the process a lot.
Regards
François
I'd rather keep the vote about one thing, and one thing only.
you propose. I think, the concept of run-time declare() switch is not
designed well. It just affects VM and JITed code in negative way, because
in
each function we will have to handle both options
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-
3054389ad750ce9a9f5895cd6d27800fR3762
and also set additional flag on each call
https://github.com/ircmaxell/php-src/compare/scalar_type_hints_v5#diff-
3054389ad750ce9a9f5895cd6d27800fR2802What negative way is that? It's a clearly defined switch, kept in a
clearly defined place.And considering it's a purely compile time construct, I fail to see
how it could possibly affect either the VM or JITed code in a negative
way.Heck, if we really wanted to, we could compile a separate
ZEND_DO_FCALL opcode for strict types: ZEND_DO_STRICT_FCALL, which
hard-codes the strict data.
- resource type hint may be useful in the same way as all other types
The problem here is typing on a resource doesn't give you enough
information to be "safe":function foo(resource $bar): string {
return fread($bar);
}foo(mysql_connect(...));
I think a longer-term plan to replace (transparently) resources with
objects would be far more beneficial.
- it may make sense not to disable bool/int/float/string classes at all. we
may just don't allow them in type hints. This will break less applications.It'll still break applications, because you can no longer do:
function foo(String $string) {}
foo(new String);
I think leaving the ability to create a class named "string" while at
the same time removing the ability to type against it is not only
weird, but definitely not something I think we should do (it's just
way to inconsistent).Anthony
Hi Anthony,
I have been interested in this proposal for a while now. I'm not on internals, but I have a question about your proposal.
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed.
How would this work with namespaces?
declare(strict_types=1) namespace Foo;
namespace Bar; declare(strict_types=1)
strict namespace Baz;
Really good proposal though. Really hope it passes vote and we finally get scalar type hints in PHP.
Cheers,
Chris
Chris,
I'll edit in the proposal, but you can check the tests in the mean time:
https://github.com/ircmaxell/php-src/blob/c8590799622ddb801360664d08ac5d7f4fa342df/Zend/tests/typehints/scalar_strict_declaration_placement_002.phpt
https://github.com/ircmaxell/php-src/blob/c8590799622ddb801360664d08ac5d7f4fa342df/Zend/tests/typehints/scalar_strict_declaration_placement_004.phpt
https://github.com/ircmaxell/php-src/blob/c8590799622ddb801360664d08ac5d7f4fa342df/Zend/tests/typehints/scalar_strict_declaration_placement_005.phpt
So it needs to come before the namespace declaration (in fact, it
currently needs to be the first declaration in the file).
Though I am about to implement the block syntax, and that may alter
things slightly (though declare will be required to be outside the
namespace).
Anthony
Hi Anthony,
I have been interested in this proposal for a while now. I'm not on internals, but I have a question about your proposal.
- declare(strict_types=1) (if used) is required to be the first
instruction in the file only. No other usages allowed.How would this work with namespaces?
declare(strict_types=1) namespace Foo;
namespace Bar; declare(strict_types=1)
strict namespace Baz;
Really good proposal though. Really hope it passes vote and we finally get scalar type hints in PHP.
Cheers,
Chris