@@ -1312,12 +1312,7 @@ private function processStmtNode(
1312
1312
$ initScope = $ condResult ->getScope ();
1313
1313
$ condResultScope = $ condResult ->getScope ();
1314
1314
$ 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 ());
1321
1316
$ hasYield = $ hasYield || $ condResult ->hasYield ();
1322
1317
$ throwPoints = array_merge ($ throwPoints , $ condResult ->getThrowPoints ());
1323
1318
$ impurePoints = array_merge ($ impurePoints , $ condResult ->getImpurePoints ());
@@ -5054,7 +5049,7 @@ private function processAssignVar(
5054
5049
$ valueToWrite = $ scope ->getType ($ assignedExpr );
5055
5050
$ nativeValueToWrite = $ scope ->getNativeType ($ assignedExpr );
5056
5051
$ originalValueToWrite = $ valueToWrite ;
5057
- $ originalNativeValueToWrite = $ valueToWrite ;
5052
+ $ originalNativeValueToWrite = $ nativeValueToWrite ;
5058
5053
5059
5054
// 3. eval assigned expr
5060
5055
$ result = $ processExprCallback ($ scope );
@@ -5075,67 +5070,9 @@ private function processAssignVar(
5075
5070
}
5076
5071
$ offsetValueType = $ varType ;
5077
5072
$ 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
- }
5103
5073
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 );
5139
5076
5140
5077
if ($ varType ->isArray ()->yes () || !(new ObjectType (ArrayAccess::class))->isSuperTypeOf ($ varType )->yes ()) {
5141
5078
if ($ var instanceof Variable && is_string ($ var ->name )) {
@@ -5408,6 +5345,46 @@ static function (): void {
5408
5345
return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints );
5409
5346
}
5410
5347
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
+
5411
5388
private function unwrapAssign (Expr $ expr ): Expr
5412
5389
{
5413
5390
if ($ expr instanceof Assign) {
0 commit comments