1919use PhpParser \Node \Stmt \Else_ ;
2020use PhpParser \Node \Stmt \If_ ;
2121use PhpParser \NodeVisitor ;
22+ use PHPStan \Analyser \Scope ;
2223use PHPStan \Reflection \ClassReflection ;
2324use PHPStan \Type \IntersectionType ;
2425use Rector \DeadCode \NodeAnalyzer \SafeLeftTypeBooleanAndOrAnalyzer ;
@@ -130,7 +131,8 @@ public function refactor(Node $node): int|null|array|If_
130131 return null ;
131132 }
132133
133- if ($ this ->shouldSkipFromVariable ($ node ->cond )) {
134+ $ scope = ScopeFetcher::fetch ($ node );
135+ if ($ this ->shouldSkipFromVariable ($ node ->cond , $ scope )) {
134136 return null ;
135137 }
136138
@@ -139,7 +141,6 @@ public function refactor(Node $node): int|null|array|If_
139141 return null ;
140142 }
141143
142- $ scope = ScopeFetcher::fetch ($ node );
143144 $ type = $ scope ->getNativeType ($ node ->cond );
144145 if (! $ type ->isTrue ()->yes ()) {
145146 return null ;
@@ -165,12 +166,18 @@ public function refactor(Node $node): int|null|array|If_
165166 return $ node ->stmts ;
166167 }
167168
168- private function shouldSkipFromVariable (Expr $ expr ): bool
169+ private function shouldSkipFromVariable (Expr $ expr, Scope $ scope ): bool
169170 {
170171 /** @var Variable[] $variables */
171172 $ variables = $ this ->betterNodeFinder ->findInstancesOf ($ expr , [Variable::class]);
172173
173174 foreach ($ variables as $ variable ) {
175+ // maybe undefined variable is treated as null on some code paths, so the condition is not always true
176+ $ variableName = $ this ->getName ($ variable );
177+ if (is_string ($ variableName ) && ! $ scope ->hasVariableType ($ variableName )->yes ()) {
178+ return true ;
179+ }
180+
174181 if ($ this ->exprAnalyzer ->isNonTypedFromParam ($ variable )) {
175182 return true ;
176183 }
0 commit comments