Skip to content

Conversation

rajyan
Copy link
Contributor

@rajyan rajyan commented Nov 1, 2022

Steps left

  • permit all expression types as conditional expression keys
  • change the type guard logic by using the specified scope
  • Improve createConditionalExpressions
  • fix conditional expression invalidations
  • use ExpressionTypeHolders for conditions
  • change addConditionalExpressions first arg to expr

fixes phpstan/phpstan#3677
fixes phpstan/phpstan#5623
fixes phpstan/phpstan#5401 (the playground in the comment is another issue, we should open a new issue)
fixes phpstan/phpstan#7292
fixes phpstan/phpstan#8212

@rajyan rajyan force-pushed the conditional-expressions branch 4 times, most recently from edc1a3d to 0ae0fe3 Compare November 6, 2022 09:57
@rajyan rajyan marked this pull request as ready for review November 6, 2022 09:57
@rajyan rajyan marked this pull request as draft November 6, 2022 09:57
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@rajyan
Copy link
Contributor Author

rajyan commented Nov 6, 2022

Sorry miss clicked

@rajyan rajyan force-pushed the conditional-expressions branch from 5b443e3 to 0537707 Compare November 6, 2022 12:30
@rajyan
Copy link
Contributor Author

rajyan commented Nov 6, 2022

I think we can clean up the conditional expression logic, and make it easier to migrate to LateResolvableTypes

@rajyan
Copy link
Contributor Author

rajyan commented Nov 6, 2022

@rajyan
Copy link
Contributor Author

rajyan commented Nov 6, 2022

Steps left

  1. Improve createConditionalExpressions
  2. fix conditional expression invalidations
  3. use ExpressionTypeHolders for conditions
  4. change addConditionalExpressions first arg to expr

@rajyan
Copy link
Contributor Author

rajyan commented Nov 6, 2022

Another note,

We need to carefully separate assign and specifying

// when $b is conditional of $a = 'foo' => 'foo', $a = 'bar' => 'bar'
echo $b; // 'foo'|'bar'
if ($a === 'foo') {
  echo $b; // 'foo'
}
if ($a === 'bar') {
  echo $b; // 'bar'
}
if ($a === 'foo') {
  $a = 'bar';
  echo $b; // 'foo'
}
$a = 'foo';
echo $b;  // 'foo'|'bar'

Assign is a overwrite and needs invalidation of related resolved expression types, while specifying should be an intersection and no need to invalidate in my opinion.

@rajyan rajyan force-pushed the conditional-expressions branch 3 times, most recently from ee5afc6 to 6bcd89f Compare November 7, 2022 13:46
@ondrejmirtes
Copy link
Member

BTW just a minor nitpick - "temporal" is related to time, "temporary" is what you want here :)

@ondrejmirtes
Copy link
Member

BTW there are some commented-out tests here https://github.com/phpstan/phpstan-src/blob/1.9.x/tests/PHPStan/Analyser/data/dependent-variable-certainty.php, maybe you could debug that as part of this or some future PR :)

@rajyan rajyan force-pushed the conditional-expressions branch from 6bcd89f to 113fe01 Compare November 7, 2022 23:48
@ondrejmirtes ondrejmirtes force-pushed the conditional-expressions branch 2 times, most recently from 7cee285 to 7af49fe Compare November 8, 2022 14:14
@ondrejmirtes
Copy link
Member

This fixes some issues: https://github.com/phpstan/phpstan-src/actions/runs/3420191417

Would be nice to add regression tests here for those which are fixed, to make sure they don't get broken in future iterations.

@rajyan
Copy link
Contributor Author

rajyan commented Nov 8, 2022

@ondrejmirtes
The new issue bot CI looks so wonderful!👍
Thank you for it.

@rajyan rajyan force-pushed the conditional-expressions branch 2 times, most recently from e8f1aac to cbbc81e Compare November 8, 2022 22:46
@rajyan
Copy link
Contributor Author

rajyan commented Nov 9, 2022

Memo
SpecifyExpressionType and assignExpression with certanity maybe

@rajyan rajyan force-pushed the conditional-expressions branch 3 times, most recently from 9def4f8 to 0260db9 Compare November 9, 2022 13:03
@rajyan rajyan force-pushed the conditional-expressions branch from 76bb087 to 9659803 Compare November 13, 2022 03:34
@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

I'm gonna revert changes in createConditionalExpressions of mergeWith for now, because the pull request is getting to large... The changes in this PR can fix a lot of dependant type issues already:smile:

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

What I did in this pull request

  1. Separated specifying and assigning
  • Only invalidate conditionalExpressions in assigning
  1. Changed logic of filtering conditionalExpressions
  • Use getType when to check matching expressions (to make conditionalExpressions work for all expressions)
  1. Refactored the unsetExpression logic

@rajyan rajyan force-pushed the conditional-expressions branch from 9659803 to faf2da9 Compare November 13, 2022 03:46
@rajyan rajyan changed the title [wip] conditional expression types for all expressions Conditional expression types for all expressions Nov 13, 2022
@rajyan rajyan force-pushed the conditional-expressions branch from faf2da9 to 40ba7ec Compare November 13, 2022 03:54
@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

I think this pull request is mergable now.
The steps left are

  • Use ExpressionTypeHolders for ConditionalExpressionTypes conditions (to get rid of exprStringToExpr)
  • Make createConditionalExpressions to work for all expressions
  • Make processBooleanConditionalTypes to work for all expressions
  • improve addConditionalExpressions

and then, we can change ConditionalExpressions to LateResolvableType.

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

The phpunit integration test failure seems related

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

Found that specified types from getNewConditionalExpressionHolders is wrong in some cases.
I'll create another pull request and fix it there.

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

What I'm saying wrong, is this
image
created from

if ($loaded === false || ($strict && $message !== '')) {

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

Fixed another bug and I think this is finally ready!

@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

The error of rector is legit, but the error message should be improved.
https://github.com/rectorphp/rector-src/blob/71b1142ee41eceef21d9c3d3a1bf5bc4f67ad9d2/packages/NodeTypeResolver/PHPStan/TypeHasher.php#L122

! $currentType instanceof AliasedObjectType

is always false, because it's narrowed in the previous line.

@rajyan rajyan marked this pull request as ready for review November 13, 2022 13:51
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@rajyan rajyan changed the title Conditional expression types for all expressions Improve conditionalExpressionTypes Nov 13, 2022
@herndlm
Copy link
Contributor

herndlm commented Nov 13, 2022

Does it make sense to also add assertType() checks to the dependable type related fixed issues? I was looking forward to those in the diff :) The same issue files could be reused in NodeScopeResolverTest.

@ondrejmirtes ondrejmirtes merged commit c9d26e6 into phpstan:1.9.x Nov 13, 2022
@ondrejmirtes
Copy link
Member

Awesome, thank you! Looking to other improvements :)

@ondrejmirtes
Copy link
Member

What doesn't sit well with me and what you haven't changed yet is the places in NodeScopeResolver where addConditionalExpressions are called. It's only for variables so it doesn't work generally for all expressions :)

@rajyan rajyan deleted the conditional-expressions branch November 13, 2022 22:03
@rajyan
Copy link
Contributor Author

rajyan commented Nov 13, 2022

@herndlm
Yeah, I'll add them!

@ondrejmirtes
Created a ConditionalExpressionTypes todos to remember what to do, and make others can work on it too if someone is interested.
phpstan/phpstan#8360

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment