1515use PHPStan \Analyser \ExpressionResultStorage ;
1616use PHPStan \Analyser \ExprHandler ;
1717use PHPStan \Analyser \ExprHandler \Helper \DefaultNarrowingHelper ;
18+ use PHPStan \Analyser \ExprHandler \Helper \IllegalOffsetTypeHelper ;
1819use PHPStan \Analyser \ExprHandler \Helper \MethodCallReturnTypeHelper ;
1920use PHPStan \Analyser \ExprHandler \Helper \MethodThrowPointHelper ;
2021use PHPStan \Analyser \Generics \TemplateArgumentFrame ;
22+ use PHPStan \Analyser \InternalThrowPoint ;
2123use PHPStan \Analyser \IssetabilityDescriptor ;
2224use PHPStan \Analyser \MutatingScope ;
2325use PHPStan \Analyser \NodeScopeResolver ;
2931use PHPStan \Dependency \Dependencies ;
3032use PHPStan \DependencyInjection \AutowiredService ;
3133use PHPStan \Node \Expr \TypeExpr ;
34+ use PHPStan \Php \PhpVersion ;
3235use PHPStan \Reflection \ParametersAcceptorSelector ;
3336use PHPStan \Turbo \ShadowedByTurboExtension ;
3437use PHPStan \Type \ErrorType ;
3538use PHPStan \Type \NeverType ;
3639use PHPStan \Type \ObjectType ;
3740use PHPStan \Type \Type ;
3841use PHPStan \Type \TypeCombinator ;
42+ use TypeError ;
3943use function array_merge ;
4044use function is_string ;
4145
@@ -52,6 +56,7 @@ public function __construct(
5256 private DefaultNarrowingHelper $ defaultNarrowingHelper ,
5357 private MethodThrowPointHelper $ methodThrowPointHelper ,
5458 private MethodCallReturnTypeHelper $ methodCallReturnTypeHelper ,
59+ private PhpVersion $ phpVersion ,
5560 )
5661 {
5762 }
@@ -130,6 +135,16 @@ public function composeResult(NodeScopeResolver $nodeScopeResolver, Stmt $stmt,
130135 $ offsetGetCall = new MethodCall ($ expr ->var , new Identifier ('offsetGet ' ), [new Arg ($ expr ->dim )], [TemplateArgumentFrame::SYNTHETIC_SITE_ATTRIBUTE => true ]);
131136 }
132137
138+ if (
139+ $ this ->phpVersion ->throwsTypeErrorForIllegalOffsets ()
140+ // only array and string offset reads throw TypeError for illegal offsets,
141+ // reads on null and other scalars emit a warning, ArrayAccess objects go through offsetGet()
142+ && (!$ varType ->isArray ()->no () || !$ varType ->isString ()->no ())
143+ && IllegalOffsetTypeHelper ::mayOffsetThrowTypeError ($ dimResult ->getType ())
144+ ) {
145+ $ throwPoints [] = InternalThrowPoint ::createExplicit ($ scope , new ObjectType (TypeError::class), $ expr , false );
146+ }
147+
133148 $ result = $ this ->expressionResultFactory ->create (
134149 $ scope ,
135150 beforeScope: $ beforeScope ,
0 commit comments