@@ -1312,12 +1312,7 @@ private function processStmtNode(
13121312 $ initScope = $ condResult ->getScope ();
13131313 $ condResultScope = $ condResult ->getScope ();
13141314 $ condTruthiness = ($ this ->treatPhpDocTypesAsCertain ? $ condResultScope ->getType ($ condExpr ) : $ condResultScope ->getNativeType ($ condExpr ))->toBoolean ();
1315- if ($ condTruthiness instanceof ConstantBooleanType) {
1316- $ condTruthinessTrinary = TrinaryLogic::createFromBoolean ($ condTruthiness ->getValue ());
1317- } else {
1318- $ condTruthinessTrinary = TrinaryLogic::createMaybe ();
1319- }
1320- $ isIterableAtLeastOnce = $ isIterableAtLeastOnce ->and ($ condTruthinessTrinary );
1315+ $ isIterableAtLeastOnce = $ isIterableAtLeastOnce ->and ($ condTruthiness ->isTrue ());
13211316 $ hasYield = $ hasYield || $ condResult ->hasYield ();
13221317 $ throwPoints = array_merge ($ throwPoints , $ condResult ->getThrowPoints ());
13231318 $ impurePoints = array_merge ($ impurePoints , $ condResult ->getImpurePoints ());
@@ -5054,7 +5049,7 @@ private function processAssignVar(
50545049 $ valueToWrite = $ scope ->getType ($ assignedExpr );
50555050 $ nativeValueToWrite = $ scope ->getNativeType ($ assignedExpr );
50565051 $ originalValueToWrite = $ valueToWrite ;
5057- $ originalNativeValueToWrite = $ valueToWrite ;
5052+ $ originalNativeValueToWrite = $ nativeValueToWrite ;
50585053
50595054 // 3. eval assigned expr
50605055 $ result = $ processExprCallback ($ scope );
@@ -5075,67 +5070,9 @@ private function processAssignVar(
50755070 }
50765071 $ offsetValueType = $ varType ;
50775072 $ offsetNativeValueType = $ varNativeType ;
5078- $ offsetValueTypeStack = [$ offsetValueType ];
5079- $ offsetValueNativeTypeStack = [$ offsetNativeValueType ];
5080- foreach (array_slice ($ offsetTypes , 0 , -1 ) as $ offsetType ) {
5081- if ($ offsetType === null ) {
5082- $ offsetValueType = new ConstantArrayType ([], []);
5083-
5084- } else {
5085- $ offsetValueType = $ offsetValueType ->getOffsetValueType ($ offsetType );
5086- if ($ offsetValueType instanceof ErrorType) {
5087- $ offsetValueType = new ConstantArrayType ([], []);
5088- }
5089- }
5090-
5091- $ offsetValueTypeStack [] = $ offsetValueType ;
5092- }
5093- foreach (array_slice ($ offsetNativeTypes , 0 , -1 ) as $ offsetNativeType ) {
5094- if ($ offsetNativeType === null ) {
5095- $ offsetNativeValueType = new ConstantArrayType ([], []);
5096-
5097- } else {
5098- $ offsetNativeValueType = $ offsetNativeValueType ->getOffsetValueType ($ offsetNativeType );
5099- if ($ offsetNativeValueType instanceof ErrorType) {
5100- $ offsetNativeValueType = new ConstantArrayType ([], []);
5101- }
5102- }
51035073
5104- $ offsetValueNativeTypeStack [] = $ offsetNativeValueType ;
5105- }
5106-
5107- foreach (array_reverse ($ offsetTypes ) as $ i => $ offsetType ) {
5108- /** @var Type $offsetValueType */
5109- $ offsetValueType = array_pop ($ offsetValueTypeStack );
5110- if (!$ offsetValueType instanceof MixedType) {
5111- $ types = [
5112- new ArrayType (new MixedType (), new MixedType ()),
5113- new ObjectType (ArrayAccess::class),
5114- new NullType (),
5115- ];
5116- if ($ offsetType !== null && $ offsetType ->isInteger ()->yes ()) {
5117- $ types [] = new StringType ();
5118- }
5119- $ offsetValueType = TypeCombinator::intersect ($ offsetValueType , TypeCombinator::union (...$ types ));
5120- }
5121- $ valueToWrite = $ offsetValueType ->setOffsetValueType ($ offsetType , $ valueToWrite , $ i === 0 );
5122- }
5123- foreach (array_reverse ($ offsetNativeTypes ) as $ i => $ offsetNativeType ) {
5124- /** @var Type $offsetNativeValueType */
5125- $ offsetNativeValueType = array_pop ($ offsetValueNativeTypeStack );
5126- if (!$ offsetNativeValueType instanceof MixedType) {
5127- $ types = [
5128- new ArrayType (new MixedType (), new MixedType ()),
5129- new ObjectType (ArrayAccess::class),
5130- new NullType (),
5131- ];
5132- if ($ offsetNativeType !== null && $ offsetNativeType ->isInteger ()->yes ()) {
5133- $ types [] = new StringType ();
5134- }
5135- $ offsetNativeValueType = TypeCombinator::intersect ($ offsetNativeValueType , TypeCombinator::union (...$ types ));
5136- }
5137- $ nativeValueToWrite = $ offsetNativeValueType ->setOffsetValueType ($ offsetNativeType , $ nativeValueToWrite , $ i === 0 );
5138- }
5074+ $ valueToWrite = $ this ->produceArrayDimFetchAssignValueToWrite ($ offsetTypes , $ offsetValueType , $ valueToWrite );
5075+ $ nativeValueToWrite = $ this ->produceArrayDimFetchAssignValueToWrite ($ offsetNativeTypes , $ offsetNativeValueType , $ nativeValueToWrite );
51395076
51405077 if ($ varType ->isArray ()->yes () || !(new ObjectType (ArrayAccess::class))->isSuperTypeOf ($ varType )->yes ()) {
51415078 if ($ var instanceof Variable && is_string ($ var ->name )) {
@@ -5408,6 +5345,46 @@ static function (): void {
54085345 return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints );
54095346 }
54105347
5348+ /**
5349+ * @param list<Type|null> $offsetTypes
5350+ */
5351+ private function produceArrayDimFetchAssignValueToWrite (array $ offsetTypes , Type $ offsetValueType , Type $ valueToWrite ): Type
5352+ {
5353+ $ offsetValueTypeStack = [$ offsetValueType ];
5354+ foreach (array_slice ($ offsetTypes , 0 , -1 ) as $ offsetType ) {
5355+ if ($ offsetType === null ) {
5356+ $ offsetValueType = new ConstantArrayType ([], []);
5357+
5358+ } else {
5359+ $ offsetValueType = $ offsetValueType ->getOffsetValueType ($ offsetType );
5360+ if ($ offsetValueType instanceof ErrorType) {
5361+ $ offsetValueType = new ConstantArrayType ([], []);
5362+ }
5363+ }
5364+
5365+ $ offsetValueTypeStack [] = $ offsetValueType ;
5366+ }
5367+
5368+ foreach (array_reverse ($ offsetTypes ) as $ i => $ offsetType ) {
5369+ /** @var Type $offsetValueType */
5370+ $ offsetValueType = array_pop ($ offsetValueTypeStack );
5371+ if (!$ offsetValueType instanceof MixedType) {
5372+ $ types = [
5373+ new ArrayType (new MixedType (), new MixedType ()),
5374+ new ObjectType (ArrayAccess::class),
5375+ new NullType (),
5376+ ];
5377+ if ($ offsetType !== null && $ offsetType ->isInteger ()->yes ()) {
5378+ $ types [] = new StringType ();
5379+ }
5380+ $ offsetValueType = TypeCombinator::intersect ($ offsetValueType , TypeCombinator::union (...$ types ));
5381+ }
5382+ $ valueToWrite = $ offsetValueType ->setOffsetValueType ($ offsetType , $ valueToWrite , $ i === 0 );
5383+ }
5384+
5385+ return $ valueToWrite ;
5386+ }
5387+
54115388 private function unwrapAssign (Expr $ expr ): Expr
54125389 {
54135390 if ($ expr instanceof Assign) {
0 commit comments