Skip to content

Commit e68852a

Browse files
nishimuraondrejmirtes
authored andcommitted
Check generic type of ArrayAccess in hasOffsetValueType
1 parent 5ab5450 commit e68852a

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

src/Type/ObjectType.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,16 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic
596596
return TrinaryLogic::createNo();
597597
}
598598

599+
if ($this->isInstanceOf(\ArrayAccess::class)->yes()) {
600+
$tKey = GenericTypeVariableResolver::getType($this, \ArrayAccess::class, 'TKey');
601+
if ($tKey !== null && $tKey->isSuperTypeOf($offsetType)->no()) {
602+
return TrinaryLogic::createNo();
603+
}
604+
605+
return TrinaryLogic::createMaybe();
606+
}
607+
599608
return $this->isExtraOffsetAccessibleClass()
600-
->or($this->isInstanceOf(\ArrayAccess::class))
601609
->and(TrinaryLogic::createMaybe());
602610
}
603611

tests/PHPStan/Type/ObjectTypeTest.php

+65
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,69 @@ public function testGetClassReflectionOfGenericClass(): void
431431
$this->assertSame('Traversable<mixed,mixed>', $classReflection->getDisplayName());
432432
}
433433

434+
public function dataHasOffsetValueType(): array
435+
{
436+
return [
437+
[
438+
new ObjectType(\stdClass::class),
439+
new IntegerType(),
440+
TrinaryLogic::createNo(),
441+
],
442+
[
443+
new ObjectType(\ArrayAccess::class),
444+
new IntegerType(),
445+
TrinaryLogic::createMaybe(),
446+
],
447+
[
448+
new GenericObjectType(\ArrayAccess::class, [new IntegerType(), new MixedType()]),
449+
new IntegerType(),
450+
TrinaryLogic::createMaybe(),
451+
],
452+
[
453+
new GenericObjectType(\ArrayAccess::class, [new IntegerType(), new MixedType()]),
454+
new MixedType(),
455+
TrinaryLogic::createMaybe(),
456+
],
457+
[
458+
new GenericObjectType(\ArrayAccess::class, [new IntegerType(), new MixedType()]),
459+
new StringType(),
460+
TrinaryLogic::createNo(),
461+
],
462+
[
463+
new GenericObjectType(\ArrayAccess::class, [new ObjectType(\DateTimeInterface::class), new MixedType()]),
464+
new ObjectType(\DateTime::class),
465+
TrinaryLogic::createMaybe(),
466+
],
467+
[
468+
new GenericObjectType(\ArrayAccess::class, [new ObjectType(\DateTime::class), new MixedType()]),
469+
new ObjectType(\DateTimeInterface::class),
470+
TrinaryLogic::createMaybe(),
471+
],
472+
[
473+
new GenericObjectType(\ArrayAccess::class, [new ObjectType(\DateTime::class), new MixedType()]),
474+
new ObjectType(\stdClass::class),
475+
TrinaryLogic::createNo(),
476+
],
477+
];
478+
}
479+
480+
/**
481+
* @dataProvider dataHasOffsetValueType
482+
* @param \PHPStan\Type\ObjectType $type
483+
* @param Type $offsetType
484+
* @param TrinaryLogic $expectedResult
485+
*/
486+
public function testHasOffsetValueType(
487+
ObjectType $type,
488+
Type $offsetType,
489+
TrinaryLogic $expectedResult
490+
): void
491+
{
492+
$this->assertSame(
493+
$expectedResult->describe(),
494+
$type->hasOffsetValueType($offsetType)->describe(),
495+
sprintf('%s -> accepts(%s)', $type->describe(VerbosityLevel::precise()), $offsetType->describe(VerbosityLevel::precise()))
496+
);
497+
}
498+
434499
}

0 commit comments

Comments
 (0)