@@ -154,6 +154,10 @@ private function getMethodReturnTypeForHydrationMode(
154
154
return $ this ->originalReturnType ($ methodReflection );
155
155
}
156
156
157
+ if (null === $ queryResultType ) {
158
+ return $ this ->originalReturnType ($ methodReflection );
159
+ }
160
+
157
161
switch ($ methodReflection ->getName ()) {
158
162
case 'getSingleResult ' :
159
163
return $ queryResultType ;
@@ -187,13 +191,21 @@ private function getMethodReturnTypeForHydrationMode(
187
191
}
188
192
}
189
193
190
- private function getArrayHydratedReturnType (Type $ queryResultType ): Type
194
+ /**
195
+ * When we're array-hydrating object, we're not sure of the shape of the array.
196
+ * We could return `new ArrayTyp(new MixedType(), new MixedType())`
197
+ * but the lack of precision in the array keys/values would give false positive.
198
+ *
199
+ * @see https://github.com/phpstan/phpstan-doctrine/pull/412#issuecomment-1497092934
200
+ */
201
+ private function getArrayHydratedReturnType (Type $ queryResultType ): ?Type
191
202
{
192
203
$ objectManager = $ this ->objectMetadataResolver ->getObjectManager ();
193
204
194
- return TypeTraverser::map (
205
+ $ mixedFound = false ;
206
+ $ queryResultType = TypeTraverser::map (
195
207
$ queryResultType ,
196
- static function (Type $ type , callable $ traverse ) use ($ objectManager ): Type {
208
+ static function (Type $ type , callable $ traverse ) use ($ objectManager, & $ mixedFound ): Type {
197
209
$ isObject = (new ObjectWithoutClassType ())->isSuperTypeOf ($ type );
198
210
if ($ isObject ->no ()) {
199
211
return $ traverse ($ type );
@@ -203,25 +215,35 @@ static function (Type $type, callable $traverse) use ($objectManager): Type {
203
215
|| !$ type instanceof TypeWithClassName
204
216
|| $ objectManager === null
205
217
) {
218
+ $ mixedFound = true ;
219
+
206
220
return new MixedType ();
207
221
}
208
222
209
223
if (!$ objectManager ->getMetadataFactory ()->hasMetadataFor ($ type ->getClassName ())) {
210
224
return $ traverse ($ type );
211
225
}
212
226
213
- // We could return `new ArrayTyp(new MixedType(), new MixedType())`
214
- // but the lack of precision in the array keys/values would give false positive
215
- // @see https://github.com/phpstan/phpstan-doctrine/pull/412#issuecomment-1497092934
227
+ $ mixedFound = true ;
228
+
216
229
return new MixedType ();
217
230
}
218
231
);
232
+
233
+ return $ mixedFound ? null : $ queryResultType ;
219
234
}
220
235
221
- private function getScalarHydratedReturnType (Type $ queryResultType ): Type
236
+ /**
237
+ * When we're scalar-hydrating object, we're not sure of the shape of the array.
238
+ * We could return `new ArrayTyp(new MixedType(), new MixedType())`
239
+ * but the lack of precision in the array keys/values would give false positive.
240
+ *
241
+ * @see https://github.com/phpstan/phpstan-doctrine/pull/453#issuecomment-1895415544
242
+ */
243
+ private function getScalarHydratedReturnType (Type $ queryResultType ): ?Type
222
244
{
223
245
if (!$ queryResultType ->isArray ()->yes ()) {
224
- return new ArrayType ( new MixedType (), new MixedType ()) ;
246
+ return null ;
225
247
}
226
248
227
249
foreach ($ queryResultType ->getArrays () as $ arrayType ) {
@@ -231,34 +253,37 @@ private function getScalarHydratedReturnType(Type $queryResultType): Type
231
253
!(new ObjectWithoutClassType ())->isSuperTypeOf ($ itemType )->no ()
232
254
|| !$ itemType ->isArray ()->no ()
233
255
) {
234
- return new ArrayType (new MixedType (), new MixedType ());
256
+ // We could return `new ArrayTyp(new MixedType(), new MixedType())`
257
+ // but the lack of precision in the array keys/values would give false positive
258
+ // @see https://github.com/phpstan/phpstan-doctrine/pull/453#issuecomment-1895415544
259
+ return null ;
235
260
}
236
261
}
237
262
238
263
return $ queryResultType ;
239
264
}
240
265
241
- private function getSimpleObjectHydratedReturnType (Type $ queryResultType ): Type
266
+ private function getSimpleObjectHydratedReturnType (Type $ queryResultType ): ? Type
242
267
{
243
268
if ((new ObjectWithoutClassType ())->isSuperTypeOf ($ queryResultType )->yes ()) {
244
269
return $ queryResultType ;
245
270
}
246
271
247
- return new MixedType () ;
272
+ return null ;
248
273
}
249
274
250
- private function getSingleScalarHydratedReturnType (Type $ queryResultType ): Type
275
+ private function getSingleScalarHydratedReturnType (Type $ queryResultType ): ? Type
251
276
{
252
277
$ queryResultType = $ this ->getScalarHydratedReturnType ($ queryResultType );
253
- if (!$ queryResultType ->isConstantArray ()->yes ()) {
254
- return new MixedType () ;
278
+ if (null === $ queryResultType || !$ queryResultType ->isConstantArray ()->yes ()) {
279
+ return null ;
255
280
}
256
281
257
282
$ types = [];
258
283
foreach ($ queryResultType ->getConstantArrays () as $ constantArrayType ) {
259
284
$ values = $ constantArrayType ->getValueTypes ();
260
285
if (count ($ values ) !== 1 ) {
261
- return new MixedType () ;
286
+ return null ;
262
287
}
263
288
264
289
$ types [] = $ constantArrayType ->getFirstIterableValueType ();
@@ -267,18 +292,18 @@ private function getSingleScalarHydratedReturnType(Type $queryResultType): Type
267
292
return TypeCombinator::union (...$ types );
268
293
}
269
294
270
- private function getScalarColumnHydratedReturnType (Type $ queryResultType ): Type
295
+ private function getScalarColumnHydratedReturnType (Type $ queryResultType ): ? Type
271
296
{
272
297
$ queryResultType = $ this ->getScalarHydratedReturnType ($ queryResultType );
273
- if (!$ queryResultType ->isConstantArray ()->yes ()) {
274
- return new MixedType () ;
298
+ if (null === $ queryResultType || !$ queryResultType ->isConstantArray ()->yes ()) {
299
+ return null ;
275
300
}
276
301
277
302
$ types = [];
278
303
foreach ($ queryResultType ->getConstantArrays () as $ constantArrayType ) {
279
304
$ values = $ constantArrayType ->getValueTypes ();
280
305
if (count ($ values ) !== 1 ) {
281
- return new MixedType () ;
306
+ return null ;
282
307
}
283
308
284
309
$ types [] = $ constantArrayType ->getFirstIterableValueType ();
0 commit comments