[RFC][DISCUSSION] strict_operators directive
| From: | Arnold Daniels | Date: | Thu, 16 May 2019 20:21:18 +0000 |
| Subject: | [RFC][DISCUSSION] strict_operators directive | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-105726@lists.php.net to get a copy of this message | ||
I'd like to discuss the addition of the new directive
strict_operators, which can
be used to disable type juggling when using operators.
---
MOTIVATION
A substantial part of the PHP dev community, including myself, have a strong dislike of type
juggling. It's a common source of issues, while the benefits over explicit type casting are
minimal.
The loose comparison equal (==) operator and not equal (!=) are a well
known causes of security issues. While to use of these two operators are discouraged, the issues
aren't limited to them but also present in all other comparison operators as well as arithmetic
operators.
Type juggling can be a source of frustration, as it may lead to unexpected results. An example;
Universal rules of logic state that if a > b and b > c then a
> c
<?php
$a = '42';
$b = 10;
$c = '9 dwarfs';
var_export($a > $b); // true
var_export($b > $c); // true
var_export($a > $c); // false ??
---
PROPOSAL
The strict_operators directive would work similar to strict_types. If
strict_operators=1 is declared, operators will throw a TypeError when an
operator is used with incompatible types.
<?php
declare(strict_operators=1);
$b = 10;
$c = '9 dwarfs';
var_export($b > $c); // TypeError "Type mismatch for greater than ('>')
operator with integer and string"
Including the equals operator;
<?php
declare(strict_operators=1);
$q = 42;
$r = '42';
$s = '42 dwarfs';
var_export($q == $r); // TypeError "Type mismatch for equals ('==') operator with
integer and string"
var_export($q == $s); // TypeError "Type mismatch for equals ('==') operator with
integer and string"
var_export($r == $s); // false
var_export($q === $r); // false
var_export($q == (int)$r); // true
You'd still use === to compare values of different types.
The rule also applies to arithmetic operators;
<?php
declare(strict_operators=1);
$b = 10;
$c = '9 dwarfs';
var_export($b + $c); // TypeError "Type mismatch for addition ('+') operator with
integer and string"
var_export($b + (int)$c); // 19
Using operator on a type that doesn't support it, would also throw a TypeError,
rather than trigger a notice.
<?php
declare(strict_operators=1);
$s = "foo";
$arr = [];
$b = $s . $arr; // TypeError "Unsupported type for concatenation ('.') operator,
unexpected array"
Last, it would disable type conversion for numeric strings.
<?php
declare(strict_operators=1);
$a = "2.7e1";
$b = "27";
var_dump($a == $b); // false
var_dump((int)$a == (int)$b); // true
---
SCOPE
The directive should only apply to operators and not have other side effects.
For instance; Type casting can still cause similar issues to type juggling, especially when casting
a string to an integer. In other languages like Python, casting "42 dwarfs" to an int
throws a ValueError. However, this and similar issues are outside the scope of this
proposal.
---
I believe the directive strict_operators fits in the direction PHP is going with better
support for typing, while not affecting backwards compatibility.
Regards,
Arnold Daniels
[Arnold Daniels - Contact Using
Spike](https://www.spikenow.com/?ref=spike-organic-signature&_ts=prm5vi)