@@ -84,6 +84,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
8484 $ parametersAcceptor = null ;
8585 $ constructorReflection = null ;
8686 $ classReflection = null ;
87+ $ isDynamic = false ;
8788 $ hasYield = false ;
8889 $ throwPoints = [];
8990 $ impurePoints = [];
@@ -92,7 +93,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
9293 if ($ expr ->class instanceof Name) {
9394 $ className = $ scope ->resolveName ($ expr ->class );
9495
95- [$ constructorReflection , $ classReflection , $ parametersAcceptor , $ constructorImpurePoints ] = $ this ->processConstructorReflection ($ className , $ expr , $ scope );
96+ [$ constructorReflection , $ classReflection , $ parametersAcceptor , $ constructorImpurePoints ] = $ this ->processConstructorReflection ($ className , $ expr , $ scope, false );
9697 $ impurePoints = array_merge ($ impurePoints , $ constructorImpurePoints );
9798
9899 if ($ parametersAcceptor !== null ) {
@@ -153,6 +154,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
153154 $ nodeScopeResolver ->processStmtNode ($ expr ->class , $ scope , $ storage , $ nodeCallback , StatementContext::createTopLevel ());
154155 }
155156 } else {
157+ $ isDynamic = true ;
156158 $ objectClasses = $ scope ->getType ($ expr )->getObjectClassNames ();
157159 if (count ($ objectClasses ) === 1 ) {
158160 $ objectExprResult = $ nodeScopeResolver ->processExprNode ($ stmt , new New_ (new Name ($ objectClasses [0 ])), $ scope , $ storage , new NoopNodeCallback (), $ context ->enterDeep ());
@@ -172,7 +174,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
172174 $ throwPoints = array_merge ($ throwPoints , $ additionalThrowPoints );
173175
174176 if ($ className !== null ) {
175- [$ constructorReflection , $ classReflection , $ parametersAcceptor , $ constructorImpurePoints ] = $ this ->processConstructorReflection ($ className , $ expr , $ scope );
177+ [$ constructorReflection , $ classReflection , $ parametersAcceptor , $ constructorImpurePoints ] = $ this ->processConstructorReflection ($ className , $ expr , $ scope, true );
176178 $ impurePoints = array_merge ($ impurePoints , $ constructorImpurePoints );
177179 } else {
178180 $ impurePoints [] = new ImpurePoint (
@@ -202,7 +204,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
202204 if ($ constructorThrowPoint !== null ) {
203205 $ throwPoints [] = $ constructorThrowPoint ;
204206 }
205- } elseif ($ classReflection === null ) {
207+ } elseif ($ classReflection === null || ( $ isDynamic && $ constructorReflection === null && ! $ classReflection -> isFinal ()) ) {
206208 $ throwPoints [] = InternalThrowPoint::createImplicit ($ scope , $ expr );
207209 }
208210
@@ -218,7 +220,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
218220 /**
219221 * @return array{?MethodReflection, ?ClassReflection, ?ParametersAcceptor, ImpurePoint[]}
220222 */
221- private function processConstructorReflection (string $ className , New_ $ expr , MutatingScope $ scope ): array
223+ private function processConstructorReflection (string $ className , New_ $ expr , MutatingScope $ scope, bool $ isDynamic ): array
222224 {
223225 $ constructorReflection = null ;
224226 $ parametersAcceptor = null ;
@@ -257,6 +259,14 @@ private function processConstructorReflection(string $className, New_ $expr, Mut
257259 'instantiation of unknown class ' ,
258260 false ,
259261 );
262+ } elseif ($ isDynamic && !$ classReflection ->isFinal ()) {
263+ $ impurePoints [] = new ImpurePoint (
264+ $ scope ,
265+ $ expr ,
266+ 'new ' ,
267+ sprintf ('instantiation of class %s ' , $ classReflection ->getDisplayName ()),
268+ false ,
269+ );
260270 }
261271
262272 return [$ constructorReflection , $ classReflection , $ parametersAcceptor , $ impurePoints ];
0 commit comments