@@ -3230,7 +3230,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
32303230 } else {
32313231 $ scope = $ scope ->removeTypeFromExpression ($ expr , $ type );
32323232 }
3233- $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getType ($ expr ));
3233+ $ specifiedExpressions [$ typeSpecification ['exprString ' ]] = ExpressionTypeHolder::createYes ($ expr , $ scope ->getScopeType ($ expr ));
32343234 }
32353235
32363236 $ conditions = [];
@@ -3362,7 +3362,7 @@ public function isInFirstLevelStatement(): bool
33623362 return $ this ->inFirstLevelStatement ;
33633363 }
33643364
3365- public function mergeWith (?self $ otherScope ): self
3365+ public function mergeWith (?self $ otherScope, bool $ preserveVacuousConditionals = false ): self
33663366 {
33673367 if ($ otherScope === null || $ this === $ otherScope ) {
33683368 return $ this ;
@@ -3372,6 +3372,18 @@ public function mergeWith(?self $otherScope): self
33723372
33733373 $ mergedExpressionTypes = $ this ->mergeVariableHolders ($ ourExpressionTypes , $ theirExpressionTypes );
33743374 $ conditionalExpressions = $ this ->intersectConditionalExpressions ($ otherScope ->conditionalExpressions );
3375+ if ($ preserveVacuousConditionals ) {
3376+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3377+ $ conditionalExpressions ,
3378+ $ this ->conditionalExpressions ,
3379+ $ theirExpressionTypes ,
3380+ );
3381+ $ conditionalExpressions = $ this ->preserveVacuousConditionalExpressions (
3382+ $ conditionalExpressions ,
3383+ $ otherScope ->conditionalExpressions ,
3384+ $ ourExpressionTypes ,
3385+ );
3386+ }
33753387 $ conditionalExpressions = $ this ->createConditionalExpressions (
33763388 $ conditionalExpressions ,
33773389 $ ourExpressionTypes ,
@@ -3477,6 +3489,48 @@ private function intersectConditionalExpressions(array $otherConditionalExpressi
34773489 return $ newConditionalExpressions ;
34783490 }
34793491
3492+ /**
3493+ * @param array<string, ConditionalExpressionHolder[]> $currentConditionalExpressions
3494+ * @param array<string, ConditionalExpressionHolder[]> $sourceConditionalExpressions
3495+ * @param array<string, ExpressionTypeHolder> $otherExpressionTypes
3496+ * @return array<string, ConditionalExpressionHolder[]>
3497+ */
3498+ private function preserveVacuousConditionalExpressions (
3499+ array $ currentConditionalExpressions ,
3500+ array $ sourceConditionalExpressions ,
3501+ array $ otherExpressionTypes ,
3502+ ): array
3503+ {
3504+ foreach ($ sourceConditionalExpressions as $ exprString => $ holders ) {
3505+ foreach ($ holders as $ key => $ holder ) {
3506+ if (isset ($ currentConditionalExpressions [$ exprString ][$ key ])) {
3507+ continue ;
3508+ }
3509+
3510+ $ typeHolder = $ holder ->getTypeHolder ();
3511+ if ($ typeHolder ->getCertainty ()->no () && !$ typeHolder ->getExpr () instanceof Variable) {
3512+ continue ;
3513+ }
3514+
3515+ foreach ($ holder ->getConditionExpressionTypeHolders () as $ guardExprString => $ guardTypeHolder ) {
3516+ if (!array_key_exists ($ guardExprString , $ otherExpressionTypes )) {
3517+ continue ;
3518+ }
3519+
3520+ $ otherType = $ otherExpressionTypes [$ guardExprString ]->getType ();
3521+ $ guardType = $ guardTypeHolder ->getType ();
3522+
3523+ if ($ otherType ->isSuperTypeOf ($ guardType )->no ()) {
3524+ $ currentConditionalExpressions [$ exprString ][$ key ] = $ holder ;
3525+ break ;
3526+ }
3527+ }
3528+ }
3529+ }
3530+
3531+ return $ currentConditionalExpressions ;
3532+ }
3533+
34803534 /**
34813535 * @param array<string, ConditionalExpressionHolder[]> $newConditionalExpressions
34823536 * @param array<string, ConditionalExpressionHolder[]> $existingConditionalExpressions
0 commit comments