@@ -3205,7 +3205,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
32053205 } else {
32063206 $ scope = $ scope ->removeTypeFromExpression ($ expr , $ type );
32073207 }
3208- $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getType ($ expr ));
3208+ $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getScopeType ($ expr ));
32093209 }
32103210
32113211 $ conditions = [];
@@ -3337,7 +3337,7 @@ public function isInFirstLevelStatement(): bool
33373337 return $ this ->inFirstLevelStatement ;
33383338 }
33393339
3340- public function mergeWith (?self $ otherScope ): self
3340+ public function mergeWith (?self $ otherScope, bool $ preserveVacuousConditionals = false ): self
33413341 {
33423342 if ($ otherScope === null || $ this === $ otherScope ) {
33433343 return $ this ;
@@ -3347,6 +3347,18 @@ public function mergeWith(?self $otherScope): self
33473347
33483348 $ mergedExpressionTypes = $ this ->mergeVariableHolders ($ ourExpressionTypes , $ theirExpressionTypes );
33493349 $ conditionalExpressions = $ this ->intersectConditionalExpressions ($ otherScope ->conditionalExpressions );
3350+ if ($ preserveVacuousConditionals ) {
3351+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3352+ $ conditionalExpressions ,
3353+ $ this ->conditionalExpressions ,
3354+ $ theirExpressionTypes ,
3355+ );
3356+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3357+ $ conditionalExpressions ,
3358+ $ otherScope ->conditionalExpressions ,
3359+ $ ourExpressionTypes ,
3360+ );
3361+ }
33503362 $ conditionalExpressions = $ this ->createConditionalExpressions (
33513363 $ conditionalExpressions ,
33523364 $ ourExpressionTypes ,
@@ -3452,6 +3464,48 @@ private function intersectConditionalExpressions(array $otherConditionalExpressi
34523464 return $ newConditionalExpressions ;
34533465 }
34543466
3467+ /**
3468+ * @param array<string, ConditionalExpressionHolder[]> $currentConditionalExpressions
3469+ * @param array<string, ConditionalExpressionHolder[]> $sourceConditionalExpressions
3470+ * @param array<string, ExpressionTypeHolder> $otherExpressionTypes
3471+ * @return array<string, ConditionalExpressionHolder[]>
3472+ */
3473+ private function preserveVacuousConditionalExpressions (
3474+ array $ currentConditionalExpressions ,
3475+ array $ sourceConditionalExpressions ,
3476+ array $ otherExpressionTypes ,
3477+ ): array
3478+ {
3479+ foreach ($ sourceConditionalExpressions as $ exprString => $ holders ) {
3480+ foreach ($ holders as $ key => $ holder ) {
3481+ if (isset ($ currentConditionalExpressions [$ exprString ][$ key ])) {
3482+ continue ;
3483+ }
3484+
3485+ $ typeHolder = $ holder ->getTypeHolder ();
3486+ if ($ typeHolder ->getCertainty ()->no () && !$ typeHolder ->getExpr () instanceof Variable) {
3487+ continue ;
3488+ }
3489+
3490+ foreach ($ holder ->getConditionExpressionTypeHolders () as $ guardExprString => $ guardTypeHolder ) {
3491+ if (!array_key_exists ($ guardExprString , $ otherExpressionTypes )) {
3492+ continue ;
3493+ }
3494+
3495+ $ otherType = $ otherExpressionTypes [$ guardExprString ]->getType ();
3496+ $ guardType = $ guardTypeHolder ->getType ();
3497+
3498+ if ($ otherType ->isSuperTypeOf ($ guardType )->no ()) {
3499+ $ currentConditionalExpressions [$ exprString ][$ key ] = $ holder ;
3500+ break ;
3501+ }
3502+ }
3503+ }
3504+ }
3505+
3506+ return $ currentConditionalExpressions ;
3507+ }
3508+
34553509 /**
34563510 * @param array<string, ConditionalExpressionHolder[]> $newConditionalExpressions
34573511 * @param array<string, ConditionalExpressionHolder[]> $existingConditionalExpressions
0 commit comments