diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index a82287e5de..a23a25d257 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -514,6 +514,10 @@ public function isOffsetAccessible(): TrinaryLogic public function hasOffsetValueType(Type $offsetType): TrinaryLogic { + if ($this->isOffsetAccessible()->no()) { + return TrinaryLogic::createNo(); + } + return TrinaryLogic::createMaybe(); } diff --git a/tests/PHPStan/Type/MixedTypeTest.php b/tests/PHPStan/Type/MixedTypeTest.php index dfbd148dd3..7143676d7d 100644 --- a/tests/PHPStan/Type/MixedTypeTest.php +++ b/tests/PHPStan/Type/MixedTypeTest.php @@ -1030,4 +1030,62 @@ public function testSubstractedIsOffsetAccessible(MixedType $mixedType, Type $ty ); } + public function dataSubtractedHasOffsetValueType(): array + { + return [ + [ + new MixedType(), + new ArrayType(new MixedType(), new MixedType()), + new StringType(), + TrinaryLogic::createMaybe(), + ], + [ + new MixedType(), + new StringType(), + new StringType(), + TrinaryLogic::createMaybe(), + ], + [ + new MixedType(), + new ObjectType(ArrayAccess::class), + new StringType(), + TrinaryLogic::createMaybe(), + ], + [ + new MixedType(), + new UnionType([ + new ArrayType(new MixedType(), new MixedType()), + new StringType(), + new ObjectType(ArrayAccess::class), + ]), + new StringType(), + TrinaryLogic::createNo(), + ], + [ + new MixedType(), + new UnionType([ + new ArrayType(new MixedType(), new MixedType()), + new StringType(), + new ObjectType(ArrayAccess::class), + new FloatType(), + ]), + new StringType(), + TrinaryLogic::createNo(), + ], + ]; + } + + /** @dataProvider dataSubtractedHasOffsetValueType */ + public function testSubtractedHasOffsetValueType(MixedType $mixedType, Type $typeToSubtract, Type $offsetType, TrinaryLogic $expectedResult): void + { + $subtracted = $mixedType->subtract($typeToSubtract); + $actualResult = $subtracted->hasOffsetValueType($offsetType); + + $this->assertSame( + $expectedResult->describe(), + $actualResult->describe(), + sprintf('%s -> hasOffsetValueType()', $subtracted->describe(VerbosityLevel::precise())), + ); + } + }