Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Shadow ResolvedMethodReflection and ChangedTypeMethodReflection natively
The method reflection $scope->getMethodReflection() returns for nearly every
method call: ResolvedMethodReflection over ChangedTypeMethodReflection over the
PHP reflection. Both keep the twins' slots and memoization; a delegation to a
native ChangedTypeMethodReflection takes its body directly, any other wrapped
reflection one cached method site per member. pt_extended_method_reflection_call()
is that dispatch for any method reflection (the handlers' entry), next to
pt_resolved_method_reflection_new() / pt_changed_type_method_reflection_new(),
which the prototypes in TypeTraits.cpp now use. Class-map keys
resolvedMethodReflection / changedTypeMethodReflection are gone,
resolvedFunctionVariantWithOriginal is new. Differential in type-family.php.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3SmhnNkB3pEeVRTxqbdbu
  • Loading branch information
ondrejmirtes and claude committed Sep 22, 2026
commit 66e7962b8914d15ff25a3b013e1c88be14654af2
4 changes: 2 additions & 2 deletions src/Reflection/Dummy/ChangedTypeMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
use PHPStan\Reflection\ExtendedParametersAcceptor;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Turbo\ReferencedByTurboExtension;
use PHPStan\Turbo\ShadowedByTurboExtension;
use PHPStan\Type\Type;
use function count;
use function is_bool;

#[ReferencedByTurboExtension(key: 'changedTypeMethodReflection')]
#[ShadowedByTurboExtension(implementation: __DIR__ . '/../../../turbo-ext/src/ChangedTypeMethodReflection.cpp')]
final class ChangedTypeMethodReflection implements ExtendedMethodReflection
{

Expand Down
2 changes: 2 additions & 0 deletions src/Reflection/ResolvedFunctionVariantWithOriginal.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PhpParser\Node\Expr;
use PHPStan\Analyser\Generics\TemplateArgumentFrame;
use PHPStan\Reflection\Php\ExtendedDummyParameter;
use PHPStan\Turbo\ReferencedByTurboExtension;
use PHPStan\Type\ConditionalTypeForParameter;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Generic\GenericObjectType;
Expand All @@ -23,6 +24,7 @@
use WeakReference;
use function array_map;

#[ReferencedByTurboExtension(key: 'resolvedFunctionVariantWithOriginal')]
final class ResolvedFunctionVariantWithOriginal implements ResolvedFunctionVariant
{

Expand Down
4 changes: 2 additions & 2 deletions src/Reflection/ResolvedMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

use PHPStan\PhpDoc\ResolvedPhpDocBlock;
use PHPStan\TrinaryLogic;
use PHPStan\Turbo\ReferencedByTurboExtension;
use PHPStan\Turbo\ShadowedByTurboExtension;
use PHPStan\Type\Generic\TemplateTypeHelper;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\Generic\TemplateTypeVarianceMap;
use PHPStan\Type\Type;
use function is_bool;

#[ReferencedByTurboExtension(key: 'resolvedMethodReflection')]
#[ShadowedByTurboExtension(implementation: __DIR__ . '/../../turbo-ext/src/ResolvedMethodReflection.cpp')]
final class ResolvedMethodReflection implements ExtendedMethodReflection
{

Expand Down
2 changes: 1 addition & 1 deletion turbo-ext/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ if (PHP_PHPSTAN_TURBO != "no") {
// directory by splitting on backslashes only — with forward slashes the
// objects compile flat while the link list expects the subpath
EXTENSION("phpstan_turbo",
"src\\main.cpp src\\support.cpp src\\AbsorbedTemplateArgumentType.cpp src\\AcceptsResult.cpp src\\AccessoryArrayListType.cpp src\\AccessoryDecimalIntegerStringType.cpp src\\AccessoryLiteralStringType.cpp src\\AccessoryLowercaseStringType.cpp src\\AccessoryNonEmptyStringType.cpp src\\AccessoryNonFalsyStringType.cpp src\\AccessoryNumericStringType.cpp src\\AccessoryUppercaseStringType.cpp src\\ArenaCache.cpp src\\ArgsResult.cpp src\\ArrayFilterArgVisitor.cpp src\\ArrayFindArgVisitor.cpp src\\ArrayMapArgVisitor.cpp src\\ArrayOffsetNormalizingVisitor.cpp src\\ArrayType.cpp src\\ArrayWalkArgVisitor.cpp src\\ArrowFunctionArgVisitor.cpp src\\AssignTargetWalkMode.cpp src\\BenevolentUnionType.cpp src\\BooleanNarrowingHelper.cpp src\\BooleanType.cpp src\\CallableType.cpp src\\CallableTypeHelper.cpp src\\CallbackUnresolvedMethodPrototypeReflection.cpp src\\CallbackUnresolvedPropertyPrototypeReflection.cpp src\\CalledOnTypeUnresolvedMethodPrototypeReflection.cpp src\\CalledOnTypeUnresolvedPropertyPrototypeReflection.cpp src\\CircularTypeAliasErrorType.cpp src\\ClassConstantAccessType.cpp src\\ClassReflection.cpp src\\ClassStatementsGatherer.cpp src\\ClassStringType.cpp src\\ClosureArgVisitor.cpp src\\ClosureBindArgVisitor.cpp src\\ClosureBindToVarVisitor.cpp src\\ClosureType.cpp src\\CombinationsHelper.cpp src\\ConditionalExpressionHolder.cpp src\\ConditionalExpressionHolderHelper.cpp src\\ConditionalExpressionHolderRecipe.cpp src\\ConditionalType.cpp src\\ConditionalTypeForParameter.cpp src\\ConstantArrayType.cpp src\\ConstantArrayTypeBuilder.cpp src\\ConstantBooleanType.cpp src\\ConstantFloatType.cpp src\\ConstantIntegerType.cpp src\\ConstantStringType.cpp src\\ConstantTypeHelper.cpp src\\CurlSetOptArgVisitor.cpp src\\CurlSetOptArrayArgVisitor.cpp src\\DeclarePositionVisitor.cpp src\\DefaultNarrowingHelper.cpp src\\DisjunctionBranchUnionAugment.cpp src\\DisjunctionHolderProjectionAugment.cpp src\\EarlyTerminatingCallHelper.cpp src\\EndStatementResult.cpp src\\Engine.cpp src\\EnumCaseObjectType.cpp src\\ErrorType.cpp src\\ExpressionContext.cpp src\\ExpressionResult.cpp src\\ExpressionResultStorage.cpp src\\ExpressionResultStorageStack.cpp src\\ExpressionTypeHolder.cpp src\\ExprHandlerRegistry.cpp src\\ExprPrinter.cpp src\\FiniteTypeSet.cpp src\\FloatType.cpp src\\GenericClassStringType.cpp src\\GenericObjectType.cpp src\\GenericStaticType.cpp src\\GetTemplateTypeType.cpp src\\HasMethodType.cpp src\\HasOffsetType.cpp src\\HasOffsetValueType.cpp src\\HasPropertyType.cpp src\\IdenticalNarrowingHelper.cpp src\\ImmediatelyInvokedClosureVisitor.cpp src\\ImplodeArgVisitor.cpp src\\ImpurePoint.cpp src\\IntegerRangeType.cpp src\\IntegerType.cpp src\\InternalEndStatementResult.cpp src\\InternalStatementExitPoint.cpp src\\InternalStatementResult.cpp src\\InternalThrowPoint.cpp src\\IntersectionType.cpp src\\IssetabilityDescriptor.cpp src\\IsSuperTypeOfResult.cpp src\\IterableType.cpp src\\KeyOfType.cpp src\\LateResolvableArrayShapeType.cpp src\\LruCache.cpp src\\MagicConstantParamDefaultVisitor.cpp src\\MethodCallReturnTypeHelper.cpp src\\MethodThrowPointHelper.cpp src\\MixedType.cpp src\\MutatingScope.cpp src\\NativeParameterReflection.cpp src\\NeverType.cpp src\\NewAssignedToPropertyVisitor.cpp src\\NewObjectType.cpp src\\NodeScanner.cpp src\\NodeScopeResolver.cpp src\\NodeTraverser.cpp src\\NonAcceptingNeverType.cpp src\\NonEmptyArrayType.cpp src\\NonexistentParentClassType.cpp src\\NonNullabilityHelper.cpp src\\NullType.cpp src\\ObjectShapeType.cpp src\\ObjectType.cpp src\\ObjectWithoutClassType.cpp src\\OffsetAccessType.cpp src\\OversizedArrayType.cpp src\\ParentStmtTypesVisitor.cpp src\\PharForkGuard.cpp src\\PhpClassReflectionExtension.cpp src\\PhpFileCleaner.cpp src\\PreparedAssignTarget.cpp src\\RecordingNodeCallback.cpp src\\RecursionGuard.cpp src\\ReflectionAccess.cpp src\\ResourceType.cpp src\\ScalarHandler.cpp src\\ScopeContext.cpp src\\ScopeOps.cpp src\\Shadow.cpp src\\SpecifiedTypes.cpp src\\StatementContext.cpp src\\StatementExitPoint.cpp src\\StatementListWalkState.cpp src\\StatementResult.cpp src\\StatementsHandler.cpp src\\StaticType.cpp src\\StaticTypeFactory.cpp src\\StmtHandlerRegistry.cpp src\\StrictMixedType.cpp src\\StringAlwaysAcceptingObjectWithToStringType.cpp src\\StringNeverAcceptingObjectWithToStringType.cpp src\\StringType.cpp src\\SymbolFinderInFiles.cpp src\\TemplateArgumentFrame.cpp src\\TemplateArrayType.cpp src\\TemplateBenevolentUnionType.cpp src\\TemplateBooleanType.cpp src\\TemplateConstantArrayType.cpp src\\TemplateConstantIntegerType.cpp src\\TemplateConstantStringType.cpp src\\TemplateFloatType.cpp src\\TemplateGenericObjectType.cpp src\\TemplateIntegerType.cpp src\\TemplateIntersectionType.cpp src\\TemplateIterableType.cpp src\\TemplateKeyOfType.cpp src\\TemplateMixedType.cpp src\\TemplateNullType.cpp src\\TemplateObjectShapeType.cpp src\\TemplateObjectType.cpp src\\TemplateObjectWithoutClassType.cpp src\\TemplateStrictMixedType.cpp src\\TemplateStringType.cpp src\\TemplateTypeArgumentStrategy.cpp src\\TemplateTypeFactory.cpp src\\TemplateTypeHelper.cpp src\\TemplateTypeMap.cpp src\\TemplateTypeParameterStrategy.cpp src\\TemplateTypeReference.cpp src\\TemplateTypeScope.cpp src\\TemplateTypeVariance.cpp src\\TemplateTypeVarianceMap.cpp src\\TemplateUnionType.cpp src\\ThisType.cpp src\\ThrowPoint.cpp src\\TraitCollectingVisitor.cpp src\\TrinaryLogic.cpp src\\TrustedTypes.cpp src\\TryCatchTypeVisitor.cpp src\\TypeCombinator.cpp src\\TypeCombinatorCache.cpp src\\TypehintHelper.cpp src\\TypeOps.cpp src\\TypeProjectionHelper.cpp src\\TypeResult.cpp src\\TypeSpecifier.cpp src\\TypeSpecifierContext.cpp src\\TypeTraits.cpp src\\TypeTraverser.cpp src\\TypeTraverserInstanceofVisitor.cpp src\\TypeUtils.cpp src\\UnionType.cpp src\\UnionTypeHelper.cpp src\\UnresolvableTypeHelper.cpp src\\UnresolvedTemplateArgumentType.cpp src\\ValueOfType.cpp src\\VariableFlow.cpp src\\VariableFlowBuilder.cpp src\\VariableHandler.cpp src\\VariableLivenessResolver.cpp src\\VerbosityLevel.cpp src\\VoidType.cpp src\\VolatileExpressionHelper.cpp",
"src\\main.cpp src\\support.cpp src\\AbsorbedTemplateArgumentType.cpp src\\AcceptsResult.cpp src\\AccessoryArrayListType.cpp src\\AccessoryDecimalIntegerStringType.cpp src\\AccessoryLiteralStringType.cpp src\\AccessoryLowercaseStringType.cpp src\\AccessoryNonEmptyStringType.cpp src\\AccessoryNonFalsyStringType.cpp src\\AccessoryNumericStringType.cpp src\\AccessoryUppercaseStringType.cpp src\\ArenaCache.cpp src\\ArgsResult.cpp src\\ArrayFilterArgVisitor.cpp src\\ArrayFindArgVisitor.cpp src\\ArrayMapArgVisitor.cpp src\\ArrayOffsetNormalizingVisitor.cpp src\\ArrayType.cpp src\\ArrayWalkArgVisitor.cpp src\\ArrowFunctionArgVisitor.cpp src\\AssignTargetWalkMode.cpp src\\BenevolentUnionType.cpp src\\BooleanNarrowingHelper.cpp src\\BooleanType.cpp src\\CallableType.cpp src\\CallableTypeHelper.cpp src\\CallbackUnresolvedMethodPrototypeReflection.cpp src\\CallbackUnresolvedPropertyPrototypeReflection.cpp src\\CalledOnTypeUnresolvedMethodPrototypeReflection.cpp src\\CalledOnTypeUnresolvedPropertyPrototypeReflection.cpp src\\ChangedTypeMethodReflection.cpp src\\CircularTypeAliasErrorType.cpp src\\ClassConstantAccessType.cpp src\\ClassReflection.cpp src\\ClassStatementsGatherer.cpp src\\ClassStringType.cpp src\\ClosureArgVisitor.cpp src\\ClosureBindArgVisitor.cpp src\\ClosureBindToVarVisitor.cpp src\\ClosureType.cpp src\\CombinationsHelper.cpp src\\ConditionalExpressionHolder.cpp src\\ConditionalExpressionHolderHelper.cpp src\\ConditionalExpressionHolderRecipe.cpp src\\ConditionalType.cpp src\\ConditionalTypeForParameter.cpp src\\ConstantArrayType.cpp src\\ConstantArrayTypeBuilder.cpp src\\ConstantBooleanType.cpp src\\ConstantFloatType.cpp src\\ConstantIntegerType.cpp src\\ConstantStringType.cpp src\\ConstantTypeHelper.cpp src\\CurlSetOptArgVisitor.cpp src\\CurlSetOptArrayArgVisitor.cpp src\\DeclarePositionVisitor.cpp src\\DefaultNarrowingHelper.cpp src\\DisjunctionBranchUnionAugment.cpp src\\DisjunctionHolderProjectionAugment.cpp src\\EarlyTerminatingCallHelper.cpp src\\EndStatementResult.cpp src\\Engine.cpp src\\EnumCaseObjectType.cpp src\\ErrorType.cpp src\\ExpressionContext.cpp src\\ExpressionResult.cpp src\\ExpressionResultStorage.cpp src\\ExpressionResultStorageStack.cpp src\\ExpressionTypeHolder.cpp src\\ExprHandlerRegistry.cpp src\\ExprPrinter.cpp src\\FiniteTypeSet.cpp src\\FloatType.cpp src\\GenericClassStringType.cpp src\\GenericObjectType.cpp src\\GenericStaticType.cpp src\\GetTemplateTypeType.cpp src\\HasMethodType.cpp src\\HasOffsetType.cpp src\\HasOffsetValueType.cpp src\\HasPropertyType.cpp src\\IdenticalNarrowingHelper.cpp src\\ImmediatelyInvokedClosureVisitor.cpp src\\ImplodeArgVisitor.cpp src\\ImpurePoint.cpp src\\IntegerRangeType.cpp src\\IntegerType.cpp src\\InternalEndStatementResult.cpp src\\InternalStatementExitPoint.cpp src\\InternalStatementResult.cpp src\\InternalThrowPoint.cpp src\\IntersectionType.cpp src\\IssetabilityDescriptor.cpp src\\IsSuperTypeOfResult.cpp src\\IterableType.cpp src\\KeyOfType.cpp src\\LateResolvableArrayShapeType.cpp src\\LruCache.cpp src\\MagicConstantParamDefaultVisitor.cpp src\\MethodCallReturnTypeHelper.cpp src\\MethodThrowPointHelper.cpp src\\MixedType.cpp src\\MutatingScope.cpp src\\NativeParameterReflection.cpp src\\NeverType.cpp src\\NewAssignedToPropertyVisitor.cpp src\\NewObjectType.cpp src\\NodeScanner.cpp src\\NodeScopeResolver.cpp src\\NodeTraverser.cpp src\\NonAcceptingNeverType.cpp src\\NonEmptyArrayType.cpp src\\NonexistentParentClassType.cpp src\\NonNullabilityHelper.cpp src\\NullType.cpp src\\ObjectShapeType.cpp src\\ObjectType.cpp src\\ObjectWithoutClassType.cpp src\\OffsetAccessType.cpp src\\OversizedArrayType.cpp src\\ParentStmtTypesVisitor.cpp src\\PharForkGuard.cpp src\\PhpClassReflectionExtension.cpp src\\PhpFileCleaner.cpp src\\PreparedAssignTarget.cpp src\\RecordingNodeCallback.cpp src\\RecursionGuard.cpp src\\ReflectionAccess.cpp src\\ResolvedMethodReflection.cpp src\\ResourceType.cpp src\\ScalarHandler.cpp src\\ScopeContext.cpp src\\ScopeOps.cpp src\\Shadow.cpp src\\SpecifiedTypes.cpp src\\StatementContext.cpp src\\StatementExitPoint.cpp src\\StatementListWalkState.cpp src\\StatementResult.cpp src\\StatementsHandler.cpp src\\StaticType.cpp src\\StaticTypeFactory.cpp src\\StmtHandlerRegistry.cpp src\\StrictMixedType.cpp src\\StringAlwaysAcceptingObjectWithToStringType.cpp src\\StringNeverAcceptingObjectWithToStringType.cpp src\\StringType.cpp src\\SymbolFinderInFiles.cpp src\\TemplateArgumentFrame.cpp src\\TemplateArrayType.cpp src\\TemplateBenevolentUnionType.cpp src\\TemplateBooleanType.cpp src\\TemplateConstantArrayType.cpp src\\TemplateConstantIntegerType.cpp src\\TemplateConstantStringType.cpp src\\TemplateFloatType.cpp src\\TemplateGenericObjectType.cpp src\\TemplateIntegerType.cpp src\\TemplateIntersectionType.cpp src\\TemplateIterableType.cpp src\\TemplateKeyOfType.cpp src\\TemplateMixedType.cpp src\\TemplateNullType.cpp src\\TemplateObjectShapeType.cpp src\\TemplateObjectType.cpp src\\TemplateObjectWithoutClassType.cpp src\\TemplateStrictMixedType.cpp src\\TemplateStringType.cpp src\\TemplateTypeArgumentStrategy.cpp src\\TemplateTypeFactory.cpp src\\TemplateTypeHelper.cpp src\\TemplateTypeMap.cpp src\\TemplateTypeParameterStrategy.cpp src\\TemplateTypeReference.cpp src\\TemplateTypeScope.cpp src\\TemplateTypeVariance.cpp src\\TemplateTypeVarianceMap.cpp src\\TemplateUnionType.cpp src\\ThisType.cpp src\\ThrowPoint.cpp src\\TraitCollectingVisitor.cpp src\\TrinaryLogic.cpp src\\TrustedTypes.cpp src\\TryCatchTypeVisitor.cpp src\\TypeCombinator.cpp src\\TypeCombinatorCache.cpp src\\TypehintHelper.cpp src\\TypeOps.cpp src\\TypeProjectionHelper.cpp src\\TypeResult.cpp src\\TypeSpecifier.cpp src\\TypeSpecifierContext.cpp src\\TypeTraits.cpp src\\TypeTraverser.cpp src\\TypeTraverserInstanceofVisitor.cpp src\\TypeUtils.cpp src\\UnionType.cpp src\\UnionTypeHelper.cpp src\\UnresolvableTypeHelper.cpp src\\UnresolvedTemplateArgumentType.cpp src\\ValueOfType.cpp src\\VariableFlow.cpp src\\VariableFlowBuilder.cpp src\\VariableHandler.cpp src\\VariableLivenessResolver.cpp src\\VerbosityLevel.cpp src\\VoidType.cpp src\\VolatileExpressionHelper.cpp",
true,
flags);
ADD_SOURCES(configure_module_dirname + "/src/parser",
Expand Down
Loading