-
Notifications
You must be signed in to change notification settings - Fork 509
More precise types after assignment when strict-types=0 #3965
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
Conversation
This pull request has been marked as ready for review. |
I don't get why this is needed and why the current logic from #3945 doesn't already work for that. Can you explain please? |
|
This pull request has been marked as ready for review. |
@@ -0,0 +1,145 @@ | |||
<?php declare(strict_types = 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copied the test 12393 and changed only the strict_types to 0
I just forcepushed here how the code makes sense to me. We just need to fix the failing tests 😂 |
thanks for the hints.. I will look into the errors after a lunch break |
do you mean adjusting test expectations or fixing the underlying bugs? |
Fix the bugs |
ready for another review. added loads of new tests |
I didn't mean you to start changing the toCoerced... method. It we do that, we need to do it right. What I meant right now is to slightly adjust what the "else" branch in NodeScopeResolver does after my force-push. It's up to you 😊 |
I don't see a way how a slight change can fullfill the tests
could you give me an idea whats "wrong" in the current PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks promising. But you haven't touched toCoercedArgumentType
in some types. For example in ArrayTypeTrait, HasOffset*Type, accessory array types, NullType, ObjectType (Stringable object can be passed to string imho), ObjectTypeTrait.
For example VoidType should do (new NullType)->toCoercedArgumentType($strictTypes)
.
thanks for the hints. I have added support for Stringable objects and callable types. intentionally I did not add array types, as I don't find a example in which they can be coerced. I have also added tests for void type and these also did not need adjustments in |
@staabm These coercions are described on PHP website. See the links near the bottom at https://www.php.net/manual/en/language.types.type-juggling.php Converting to boolean I'm especially worried about those array accessory types because they just return this, I'm not sure what would happen for example when you have non-empty-array and try to assign it into integer, whethey it'd work properly or not. |
I think the conversion rules on these manual pages describe what happens on explicit casts. see e.g. https://3v4l.org/H5XnR while you can cast a
just added tests for the mentioned cases |
assertType('null', $this->foo); | ||
|
||
$this->fooNonNull = $this->returnVoid(); | ||
assertType('int|null', $this->foo); // should be *ERROR* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bug regarding void-to-null transformation which should be fixed in a followup PR
its a rare edge case
Oh interesting, didn't know about that. |
private string $foo; | ||
|
||
public function doFoo(callable $foo): void { | ||
$this->foo = $foo; // PHPStorm wrongly reports an error on this line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be fair PHPStan also reports an error for that (which is correct, we mostly don't differentiate between strict_types 1 or 0 in Type::accepts()
.
@@ -706,6 +706,10 @@ public function toArrayKey(): Type | |||
|
|||
public function toCoercedArgumentType(bool $strictTypes): Type | |||
{ | |||
if (!$strictTypes) { | |||
return TypeCombinator::union($this, $this->toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the object isn't a Stringable, this should just return $this
. But instead it will return ErrorType.
Also I'm not sure what happens with BcMath\Number
in strict_types=1 or 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added tests with links to 3v4l.org
Alright, I'm really excited about this, let's try it out! |
Hi @staabm, I just saw this and I have some question about this change.
|
Huhu The PR is about type inference, meaning PHPStan better know when/which types flow thru the code. It does not change the rules when errors are reported. Regarding BcMath\Number. it behaves like that because the php runtime only errors when strict_types=1, but for strict_types=0 it's legale to assign a object which implements __toString to a string. I don't know whether this makes sense. In case you want strict_types=1 you can declare it and work on the errors. ondrey might have a clear opinion on it |
The 2 different modes have different characteristics and not necessarily everyone want to migrate from weak to strict. I have recently seen discussions of php-src devs whether a new mode should be implemented which is a mix of the 2 existing ones, as both have some advantages |
@VincentLanglet This behaviour didn't change with this PR. If PHPStan reports errors in the same situations where PHP reports TypeError, it's correct. |
Improve types on top of #3945 but for the non-strict-types case.
see https://phpstan.org/r/aa5d5753-eca2-4735-bebf-6479e1ab1f42
do you think we could remove nullability from the property-type in scope, as the method we call returns a native non-nullable type, even ifstrict-types=0
...?closes phpstan/phpstan#12946
closes phpstan/phpstan#12940
closes phpstan/phpstan#12950
closes phpstan/phpstan#12947