Skip to content

Commit 6604b37

Browse files
committed
GeneratorNodeScopeResolver kick-off
1 parent 8f9490e commit 6604b37

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator;
4+
5+
/**
6+
* Work In Progress.
7+
*
8+
* This is next-get NodeScopeResolver. It aims to solve several problems:
9+
*
10+
* 1) Many expressions are processed multiple times. For example, resolving type
11+
* of BooleanAnd has to process left side in order to accurately get the type
12+
* of the right side. For things like MethodCall, even dynamic return type extensions
13+
* and ParametersAcceptorSelector are called multiple times.
14+
* 2) For complicated scope-changing expressions like assigns happening inside other expressions,
15+
* the current type inference is imprecise. Take $foo->doFoo($a = 1, $a);
16+
* When a rule hooks onto MethodCall and iterates over its args, the type of `$a`
17+
* in the second argument should be `int`, but currently it's often `mixed` because
18+
* the assignment in the first argument hasn't been processed yet in the context
19+
* where the rule is checking.
20+
*
21+
* This class (I will refer to it as GNSR from now on) aims to merge the tasks currently handled
22+
* by NodeScopeResolver, MutatingScope and TypeSpecifier all into one, because they are very similar
23+
* and their work should happen all at once without duplicit processing.
24+
*
25+
* This rewrite should fix 1) to improve performance and 2) to improve type inference precision.
26+
*
27+
* Architecture:
28+
* - Uses generators (with `yield`) for internal analysis code to handle recursive traversal
29+
* without deep call stacks and to explicitly manage when sub-expressions are analyzed
30+
* - Uses Fibers when calling custom extension code (rules, dynamic return type extensions, etc.)
31+
* to preserve backward compatibility
32+
* - Calls to `$scope->getType()` in custom extensions do not need to be preceded with `yield`.
33+
* Instead, if the type is not yet available, the call will transparently suspend the current
34+
* Fiber and resume once the type has been computed
35+
* - All computed types and analysis results are stored during traversal so that subsequent
36+
* lookups (from rules or other extensions) hit cached values with no duplicate work
37+
* - Synthetic/virtual expressions (e.g., a rule constructing `new MethodCall(...)` to query
38+
* a hypothetical method call) are analyzed on-demand when requested, with the Fiber
39+
* suspending until analysis completes
40+
*/
41+
final class GeneratorNodeScopeResolver
42+
{
43+
44+
}

0 commit comments

Comments
 (0)