@@ -294,41 +294,57 @@ public function enterDeclareStrictTypes(): self
294294 );
295295 }
296296
297- public function rememberConstructorScope (): self
297+ /**
298+ * @param array<string, ExpressionTypeHolder> $expressions
299+ * @return array<string, ExpressionTypeHolder>
300+ */
301+ private function rememberConstructorExpressions (array $ currentExpressionTypes ): array
298302 {
299303 $ expressionTypes = [];
300- foreach ($ this -> expressionTypes as $ exprString => $ expressionTypeHolder ) {
304+ foreach ($ currentExpressionTypes as $ exprString => $ expressionTypeHolder ) {
301305 $ expr = $ expressionTypeHolder ->getExpr ();
302- if (!$ expr instanceof ConstFetch) {
303- continue ;
304- }
305- $ expressionTypes [$ exprString ] = $ expressionTypeHolder ;
306- }
306+ if ($ expr instanceof PropertyFetch) {
307+ if (
308+ !$ expr ->name instanceof Node \Identifier
309+ || !$ expr ->var instanceof Variable
310+ || $ expr ->var ->name !== 'this '
311+ || !$ this ->phpVersion ->supportsReadOnlyProperties ()
312+ ) {
313+ continue ;
314+ }
307315
308- $ nativeExpressionTypes = [];
309- foreach ($ this ->nativeExpressionTypes as $ exprString => $ expressionTypeHolder ) {
310- $ expr = $ expressionTypeHolder ->getExpr ();
311- if (!$ expr instanceof ConstFetch) {
316+ $ propertyReflection = $ this ->propertyReflectionFinder ->findPropertyReflectionFromNode ($ expr , $ this );
317+ if ($ propertyReflection === null ) {
318+ continue ;
319+ }
320+
321+ $ nativePropertyReflection = $ propertyReflection ->getNativeReflection ();
322+ if ($ nativePropertyReflection === null || !$ nativePropertyReflection ->isReadOnly ()) {
323+ continue ;
324+ }
325+ } elseif (!$ expr instanceof ConstFetch) {
312326 continue ;
313327 }
314328
315- $ nativeExpressionTypes [$ exprString ] = $ expressionTypeHolder ;
329+ $ expressionTypes [$ exprString ] = $ expressionTypeHolder ;
316330 }
317331
318- if (array_key_exists ('$this ' , $ this ->expressionTypes )) {
319- $ expressionTypes ['$this ' ] = $ this ->expressionTypes ['$this ' ];
320- }
321- if (array_key_exists ('$this ' , $ this ->nativeExpressionTypes )) {
322- $ nativeExpressionTypes ['$this ' ] = $ this ->nativeExpressionTypes ['$this ' ];
332+ if (array_key_exists ('$this ' , $ currentExpressionTypes )) {
333+ $ expressionTypes ['$this ' ] = $ currentExpressionTypes ['$this ' ];
323334 }
324335
336+ return $ expressionTypes ;
337+ }
338+
339+ public function rememberConstructorScope (): self
340+ {
325341 return $ this ->scopeFactory ->create (
326342 $ this ->context ,
327343 $ this ->isDeclareStrictTypes (),
328344 $ this ->getFunction (),
329345 $ this ->getNamespace (),
330- $ expressionTypes ,
331- $ nativeExpressionTypes ,
346+ $ this -> rememberConstructorExpressions ( $ this -> expressionTypes ) ,
347+ $ this -> rememberConstructorExpressions ( $ this -> nativeExpressionTypes ) ,
332348 $ this ->conditionalExpressions ,
333349 $ this ->inClosureBindScopeClasses ,
334350 $ this ->anonymousFunctionReflection ,
@@ -3334,7 +3350,7 @@ public function enterFunction(
33343350
33353351 private function enterFunctionLike (
33363352 PhpFunctionFromParserNodeReflection $ functionReflection ,
3337- bool $ preserveThis ,
3353+ bool $ preserveConstructorScope ,
33383354 ): self
33393355 {
33403356 $ parametersByName = [];
@@ -3346,6 +3362,12 @@ private function enterFunctionLike(
33463362 $ expressionTypes = [];
33473363 $ nativeExpressionTypes = [];
33483364 $ conditionalTypes = [];
3365+
3366+ if ($ preserveConstructorScope ) {
3367+ $ expressionTypes = $ this ->rememberConstructorExpressions ($ this ->expressionTypes );
3368+ $ nativeExpressionTypes = $ this ->rememberConstructorExpressions ($ this ->nativeExpressionTypes );
3369+ }
3370+
33493371 foreach ($ functionReflection ->getParameters () as $ parameter ) {
33503372 $ parameterType = $ parameter ->getType ();
33513373
@@ -3396,13 +3418,6 @@ private function enterFunctionLike(
33963418 $ nativeExpressionTypes [$ parameterOriginalValueExprString ] = ExpressionTypeHolder::createYes ($ parameterOriginalValueExpr , $ nativeParameterType );
33973419 }
33983420
3399- if ($ preserveThis && array_key_exists ('$this ' , $ this ->expressionTypes )) {
3400- $ expressionTypes ['$this ' ] = $ this ->expressionTypes ['$this ' ];
3401- }
3402- if ($ preserveThis && array_key_exists ('$this ' , $ this ->nativeExpressionTypes )) {
3403- $ nativeExpressionTypes ['$this ' ] = $ this ->nativeExpressionTypes ['$this ' ];
3404- }
3405-
34063421 return $ this ->scopeFactory ->create (
34073422 $ this ->context ,
34083423 $ this ->isDeclareStrictTypes (),
0 commit comments