@@ -3235,7 +3235,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
32353235 } else {
32363236 $ scope = $ scope ->removeTypeFromExpression ($ expr , $ type );
32373237 }
3238- $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getType ($ expr ));
3238+ $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getScopeType ($ expr ));
32393239 }
32403240
32413241 $ conditions = [];
@@ -3368,7 +3368,7 @@ public function isInFirstLevelStatement(): bool
33683368 return $ this ->inFirstLevelStatement ;
33693369 }
33703370
3371- public function mergeWith (?self $ otherScope ): self
3371+ public function mergeWith (?self $ otherScope, bool $ preserveVacuousConditionals = false ): self
33723372 {
33733373 if ($ otherScope === null || $ this === $ otherScope ) {
33743374 return $ this ;
@@ -3378,6 +3378,18 @@ public function mergeWith(?self $otherScope): self
33783378
33793379 $ mergedExpressionTypes = $ this ->mergeVariableHolders ($ ourExpressionTypes , $ theirExpressionTypes );
33803380 $ conditionalExpressions = $ this ->intersectConditionalExpressions ($ otherScope ->conditionalExpressions );
3381+ if ($ preserveVacuousConditionals ) {
3382+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3383+ $ conditionalExpressions ,
3384+ $ this ->conditionalExpressions ,
3385+ $ theirExpressionTypes ,
3386+ );
3387+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3388+ $ conditionalExpressions ,
3389+ $ otherScope ->conditionalExpressions ,
3390+ $ ourExpressionTypes ,
3391+ );
3392+ }
33813393 $ conditionalExpressions = $ this ->createConditionalExpressions (
33823394 $ conditionalExpressions ,
33833395 $ ourExpressionTypes ,
@@ -3483,6 +3495,48 @@ private function intersectConditionalExpressions(array $otherConditionalExpressi
34833495 return $ newConditionalExpressions ;
34843496 }
34853497
3498+ /**
3499+ * @param array<string, ConditionalExpressionHolder[]> $currentConditionalExpressions
3500+ * @param array<string, ConditionalExpressionHolder[]> $sourceConditionalExpressions
3501+ * @param array<string, ExpressionTypeHolder> $otherExpressionTypes
3502+ * @return array<string, ConditionalExpressionHolder[]>
3503+ */
3504+ private function preserveVacuousConditionalExpressions (
3505+ array $ currentConditionalExpressions ,
3506+ array $ sourceConditionalExpressions ,
3507+ array $ otherExpressionTypes ,
3508+ ): array
3509+ {
3510+ foreach ($ sourceConditionalExpressions as $ exprString => $ holders ) {
3511+ foreach ($ holders as $ key => $ holder ) {
3512+ if (isset ($ currentConditionalExpressions [$ exprString ][$ key ])) {
3513+ continue ;
3514+ }
3515+
3516+ $ typeHolder = $ holder ->getTypeHolder ();
3517+ if ($ typeHolder ->getCertainty ()->no () && !$ typeHolder ->getExpr () instanceof Variable) {
3518+ continue ;
3519+ }
3520+
3521+ foreach ($ holder ->getConditionExpressionTypeHolders () as $ guardExprString => $ guardTypeHolder ) {
3522+ if (!array_key_exists ($ guardExprString , $ otherExpressionTypes )) {
3523+ continue ;
3524+ }
3525+
3526+ $ otherType = $ otherExpressionTypes [$ guardExprString ]->getType ();
3527+ $ guardType = $ guardTypeHolder ->getType ();
3528+
3529+ if ($ otherType ->isSuperTypeOf ($ guardType )->no ()) {
3530+ $ currentConditionalExpressions [$ exprString ][$ key ] = $ holder ;
3531+ break ;
3532+ }
3533+ }
3534+ }
3535+ }
3536+
3537+ return $ currentConditionalExpressions ;
3538+ }
3539+
34863540 /**
34873541 * @param array<string, ConditionalExpressionHolder[]> $newConditionalExpressions
34883542 * @param array<string, ConditionalExpressionHolder[]> $existingConditionalExpressions
0 commit comments