|
13 | 13 | use PHPStan\Analyser\ExpressionResult; |
14 | 14 | use PHPStan\Analyser\ExpressionResultStorage; |
15 | 15 | use PHPStan\Analyser\ExprHandler; |
| 16 | +use PHPStan\Analyser\ExprHandler\Helper\IllegalOffsetTypeHelper; |
16 | 17 | use PHPStan\Analyser\ExprHandler\Helper\NullsafeShortCircuitingHelper; |
| 18 | +use PHPStan\Analyser\InternalThrowPoint; |
17 | 19 | use PHPStan\Analyser\MutatingScope; |
18 | 20 | use PHPStan\Analyser\NodeScopeResolver; |
19 | 21 | use PHPStan\Analyser\NoopNodeCallback; |
|
23 | 25 | use PHPStan\Analyser\TypeSpecifierContext; |
24 | 26 | use PHPStan\DependencyInjection\AutowiredService; |
25 | 27 | use PHPStan\Node\Expr\TypeExpr; |
| 28 | +use PHPStan\Php\PhpVersion; |
26 | 29 | use PHPStan\Type\NeverType; |
27 | 30 | use PHPStan\Type\ObjectType; |
28 | 31 | use PHPStan\Type\Type; |
| 32 | +use TypeError; |
29 | 33 | use function array_merge; |
30 | 34 |
|
31 | 35 | /** |
|
35 | 39 | final class ArrayDimFetchHandler implements ExprHandler |
36 | 40 | { |
37 | 41 |
|
| 42 | + public function __construct(private PhpVersion $phpVersion) |
| 43 | + { |
| 44 | + } |
| 45 | + |
38 | 46 | public function supports(Expr $expr): bool |
39 | 47 | { |
40 | 48 | return $expr instanceof ArrayDimFetch; |
@@ -109,6 +117,16 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex |
109 | 117 | )->getThrowPoints()); |
110 | 118 | } |
111 | 119 |
|
| 120 | + if ( |
| 121 | + $this->phpVersion->throwsTypeErrorForIllegalOffsets() |
| 122 | + // only array and string offset reads throw TypeError for illegal offsets, |
| 123 | + // reads on null and other scalars emit a warning, ArrayAccess objects go through offsetGet() |
| 124 | + && (!$varType->isArray()->no() || !$varType->isString()->no()) |
| 125 | + && IllegalOffsetTypeHelper::mayOffsetThrowTypeError($scope->getType($expr->dim)) |
| 126 | + ) { |
| 127 | + $throwPoints[] = InternalThrowPoint::createExplicit($scope, new ObjectType(TypeError::class), $expr, false); |
| 128 | + } |
| 129 | + |
112 | 130 | return new ExpressionResult( |
113 | 131 | $scope, |
114 | 132 | hasYield: $dimResult->hasYield() || $varResult->hasYield(), |
|
0 commit comments