-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Parsing literal assignment of min int64 is not an integer (-9223372036854775808) #14589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
here is minimal repro: https://3v4l.org/hps4B |
Uncertain, but this may be somehow related to issue #13243 |
Thanks for the minimal repo. I wasn't aware of it prior. I was trying to convey as much detail as possible of what works and what doesn't. For now, the work-around to this issue is to just use the penultimate value and subtract one: <?php
$value = -9223372036854775807 - 1;
?> |
This is a result of how PHP parses numbers in code: I thought this was documented but I'm not finding where... edit: See php/doc-en#2400 |
Thanks @damianwadley. Looking at how other literals are formatted, I can understand the concept of what is going on with the following example. <?php
var_dump(PHP_INT_MIN); // integer
var_dump(-9223372036854775808); // literal decimal
var_dump(-0x8000000000000000); // literal hex
var_dump(-0b1000000000000000000000000000000000000000000000000000000000000000); // literal binary
var_dump(-01000000000000000000000); // literal octal
var_dump(PHP_INT_MIN === -9223372036854775808);
int(-9223372036854775808)
float(-9.223372036854776E+18)
float(-9.223372036854776E+18)
float(-9.223372036854775E+18)
float(-9.223372036854776E+18)
bool(false)
?> So with literal decimals - although technically they represent the minimum value that can be stored as an integer, they themselves are not legitimate integers. I think this edge case should be documented, as it's an odd concept to code that technically says a known/common thing, and is interpreted as another. I previously tried hunting the documentation for information (ie Type Declarations, Integer, Arithmetic Operators, Assignment Operators) about this to see if it was known behavior but came up empty. Still, this seems like a bug with the parser itself. Technically, -9223372036854775808 is a valid 64 bit integer. I know it is. Isn't it? ... isn't it? no? 😢 😭 Since it's only a problem with this specific value (-9223372036854775808), there should be a hook that detects if the string is equal to PHP_INT_MIN, and treats it as such. I mean, that's what PHP_INT_MIN is for, rite? Why else would it print out as a signed integer if we can't use that as a hard-coded value? I'm starting to find references to this issue online:
And now I'm finding a flood of bug reports |
I'm noticing that integer documentation actually does reference it, but doesn't necessarily make it explicitly clear that the literal value -9223372036854775808 on 64 bit systems will not be interpreted as an integer. To the layman, PHP "appears" to support negative integers since -9223372036854775807 is interpreted as an integer. It's a bit vague as to the limitations that it's trying to convey. It needs to come right out and say what its trying to say, or provide an example.
Needs an update/addition to clarify what it's trying to say:
|
Closing as this is a duplicate of many issues that have already been vetted and closed as well. |
Might I ask some php dev if the parsing is really that hard to be changed to parse negative integers first instead of negative operator? |
You could try, but I suspect you won’t get far. Read through some of the comments on those links I posted. Since the number is parsed separately from the negate operator, it doesn’t have the context necessary to convert to a signed integer. The problem has been rediscovered many times. The only action taken has been to update the documentation. Mind you, the documentation is not clear about the actual problem and why this specific value is not an integer. |
I belive this needs to be changed - https://github.com/php/php-src/blob/php-8.3.8/Zend/zend_ini_scanner.l#L354 - to parse signed numbers testcase/repro: https://3v4l.org/MFUWB discussion: https://bugs.php.net/bug.php?id=78081#1559116523 |
That's the INI parser. Check the zend_language files instead.
The tokenizer is a separate thing - one that doesn't have much knowledge about the actual semantics of PHP code, and I suspect something that can't be modified to tokenize a signed number without that also impacting how it tokenizes other code.
Oh hey, look at that, been five years since I |
IMHO, it's still a documentation problem. I overlooked the existing documentation since it wasn't clear that it was related to this specific scenario. Often times you can see others in the comments talking about gotchas and demonstrating examples. None of that is present. This specific issue needs to be called out as clear as daylight. A 1-line code example would go far. |
Agreed. Note that php/doc-en#2400 exists. |
Looking at zend language, it's hard to discern what is going on. It looks like negate operator is applied to an expression here as it tries to create a token. Note that the code is not aware that it is parsing a number - it just knows that it's an expression being negated. The expression Perhaps if anything were to happen, the evaluated expression of |
Description
I'm testing some edge cases with my code and started tracing a problem down to PHP itself. It turns out that assigning the minimum value of a 64 bit signed integer as a literal value ( -9223372036854775808) to a variable is not recognized as an integer. However, minimum value + 1 (-9223372036854775807) is recognized as an integer. In addition, the PHP_INT_MIN constant with the same value is recognized as an integer. Something is going on with the interpretation of numeric literals for only this specific value.
Furthermore, if I start with assigning a variable the minimum value - 1 (ie $value = -9223372036854775807 -1), then the minimum 64 bit signed value is correctly interpreted as an integer.
The following code:
Resulted in this output:
But I expected this output instead:
PHP Version
8.3.6
Operating System
No response
The text was updated successfully, but these errors were encountered: