1818use PHPStan \Type \Constant \ConstantStringType ;
1919use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
2020use PHPStan \Type \IntegerType ;
21+ use PHPStan \Type \MixedType ;
2122use PHPStan \Type \NeverType ;
2223use PHPStan \Type \Type ;
2324use PHPStan \Type \TypeCombinator ;
@@ -86,21 +87,23 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
8687 /** @var array<int|string, ConstantIntegerType|ConstantStringType> $keyTypes */
8788 $ keyTypes = [];
8889 foreach ($ argType ->getConstantArrays () as $ constantArray ) {
89- foreach ($ constantArray ->getKeyTypes () as $ i => $ keyType ) {
90+ foreach ($ constantArray ->getKeyTypes () as $ keyType ) {
9091 $ keyTypes [$ keyType ->getValue ()] = $ keyType ;
9192
92- if ($ constantArray ->isOptionalKey ($ i )) {
93- continue ;
94- }
95-
96- $ offsetValueType = $ constantArray ->getOffsetValueType ($ keyType );
97- $ offsetTypes [$ keyType ->getValue ()] = [false , $ offsetValueType ];
93+ $ hasOffset = TrinaryLogic::createFromBoolean ($ argType ->hasOffsetValueType ($ keyType )->yes ());
94+ $ offsetTypes [$ keyType ->getValue ()] = [
95+ $ hasOffset ,
96+ $ argType ->getOffsetValueType ($ keyType ),
97+ ];
9898 }
9999 }
100100
101101 if ($ keyTypes === []) {
102- foreach ($ offsetTypes as $ key => [$ generalize , $ offsetValueType ]) {
103- $ offsetTypes [$ key ][0 ] = true ;
102+ foreach ($ offsetTypes as $ key => [$ hasOffset , $ offsetValueType ]) {
103+ $ offsetTypes [$ key ] = [
104+ $ hasOffset ->and (TrinaryLogic::createMaybe ()),
105+ new MixedType (),
106+ ];
104107 }
105108 }
106109
@@ -113,8 +116,10 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
113116 }
114117
115118 $ offsetType = $ accessoryType ->getOffsetType ();
116- $ offsetValueType = $ argType ->getOffsetValueType ($ offsetType );
117- $ offsetTypes [$ offsetType ->getValue ()] = [false , $ offsetValueType ];
119+ $ offsetTypes [$ offsetType ->getValue ()] = [
120+ TrinaryLogic::createYes (),
121+ $ argType ->getOffsetValueType ($ offsetType ),
122+ ];
118123 }
119124
120125 if ($ newArrayBuilder === null ) {
@@ -172,24 +177,26 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
172177 }
173178 if ($ offsetTypes !== []) {
174179 $ knownOffsetValues = [];
175- foreach ($ offsetTypes as $ key => [$ generalize , $ offsetType ]) {
180+ foreach ($ offsetTypes as $ key => [$ hasOffset , $ offsetType ]) {
176181 if (is_int ($ key )) {
177182 // int keys will be appended and renumbered.
178183 // at this point we can't reason about them, because unknown arrays are in the mix.
179184 continue ;
180185 }
181186 $ keyType = new ConstantStringType ($ key );
182187
183- if (! $ generalize ) {
188+ if ($ hasOffset -> yes () ) {
184189 // the last string-keyed offset will overwrite previous values
185190 $ hasOffsetType = new HasOffsetValueType (
186191 $ keyType ,
187192 $ offsetType ,
188193 );
189- } else {
194+ } elseif ( $ hasOffset -> maybe ()) {
190195 $ hasOffsetType = new HasOffsetType (
191196 $ keyType ,
192197 );
198+ } else {
199+ continue ;
193200 }
194201
195202 $ knownOffsetValues [] = $ hasOffsetType ;
0 commit comments