10
10
use PHPStan \Reflection \ExtendedParametersAcceptor ;
11
11
use PHPStan \Reflection \Php \ExtendedDummyParameter ;
12
12
use PHPStan \Reflection \ResolvedMethodReflection ;
13
+ use PHPStan \Type \ThisType ;
13
14
use PHPStan \Type \Type ;
15
+ use PHPStan \Type \TypeCombinator ;
14
16
use function array_map ;
15
17
16
18
final class CallbackUnresolvedMethodPrototypeReflection implements UnresolvedMethodPrototypeReflection
@@ -82,32 +84,42 @@ public function withCalledOnType(Type $type): UnresolvedMethodPrototypeReflectio
82
84
83
85
private function transformMethodWithStaticType (ClassReflection $ declaringClass , ExtendedMethodReflection $ method ): ExtendedMethodReflection
84
86
{
85
- $ variantFn = fn (ExtendedParametersAcceptor $ acceptor ): ExtendedParametersAcceptor => new ExtendedFunctionVariant (
86
- $ acceptor ->getTemplateTypeMap (),
87
- $ acceptor ->getResolvedTemplateTypeMap (),
88
- array_map (
89
- fn (ExtendedParameterReflection $ parameter ): ExtendedParameterReflection => new ExtendedDummyParameter (
90
- $ parameter ->getName (),
91
- $ this ->transformStaticType ($ parameter ->getType ()),
92
- $ parameter ->isOptional (),
93
- $ parameter ->passedByReference (),
94
- $ parameter ->isVariadic (),
95
- $ parameter ->getDefaultValue (),
96
- $ parameter ->getNativeType (),
97
- $ this ->transformStaticType ($ parameter ->getPhpDocType ()),
98
- $ parameter ->getOutType () !== null ? $ this ->transformStaticType ($ parameter ->getOutType ()) : null ,
99
- $ parameter ->isImmediatelyInvokedCallable (),
100
- $ parameter ->getClosureThisType () !== null ? $ this ->transformStaticType ($ parameter ->getClosureThisType ()) : null ,
101
- $ parameter ->getAttributes (),
87
+ $ selfOutType = $ method ->getSelfOutType () !== null ? $ this ->transformStaticType ($ method ->getSelfOutType ()) : null ;
88
+ $ variantFn = function (ExtendedParametersAcceptor $ acceptor ) use (&$ selfOutType ): ExtendedParametersAcceptor {
89
+ $ originalReturnType = $ acceptor ->getReturnType ();
90
+ if ($ originalReturnType instanceof ThisType && $ selfOutType !== null ) {
91
+ $ returnType = TypeCombinator::intersect ($ selfOutType , $ this ->transformStaticType ($ originalReturnType ));
92
+ $ selfOutType = $ returnType ;
93
+ } else {
94
+ $ returnType = $ this ->transformStaticType ($ originalReturnType );
95
+ }
96
+ return new ExtendedFunctionVariant (
97
+ $ acceptor ->getTemplateTypeMap (),
98
+ $ acceptor ->getResolvedTemplateTypeMap (),
99
+ array_map (
100
+ fn (ExtendedParameterReflection $ parameter ): ExtendedParameterReflection => new ExtendedDummyParameter (
101
+ $ parameter ->getName (),
102
+ $ this ->transformStaticType ($ parameter ->getType ()),
103
+ $ parameter ->isOptional (),
104
+ $ parameter ->passedByReference (),
105
+ $ parameter ->isVariadic (),
106
+ $ parameter ->getDefaultValue (),
107
+ $ parameter ->getNativeType (),
108
+ $ this ->transformStaticType ($ parameter ->getPhpDocType ()),
109
+ $ parameter ->getOutType () !== null ? $ this ->transformStaticType ($ parameter ->getOutType ()) : null ,
110
+ $ parameter ->isImmediatelyInvokedCallable (),
111
+ $ parameter ->getClosureThisType () !== null ? $ this ->transformStaticType ($ parameter ->getClosureThisType ()) : null ,
112
+ $ parameter ->getAttributes (),
113
+ ),
114
+ $ acceptor ->getParameters (),
102
115
),
103
- $ acceptor ->getParameters (),
104
- ),
105
- $ acceptor ->isVariadic (),
106
- $ this ->transformStaticType ($ acceptor ->getReturnType ()),
107
- $ this ->transformStaticType ($ acceptor ->getPhpDocReturnType ()),
108
- $ this ->transformStaticType ($ acceptor ->getNativeReturnType ()),
109
- $ acceptor ->getCallSiteVarianceMap (),
110
- );
116
+ $ acceptor ->isVariadic (),
117
+ $ returnType ,
118
+ $ this ->transformStaticType ($ acceptor ->getPhpDocReturnType ()),
119
+ $ this ->transformStaticType ($ acceptor ->getNativeReturnType ()),
120
+ $ acceptor ->getCallSiteVarianceMap (),
121
+ );
122
+ };
111
123
$ variants = array_map ($ variantFn , $ method ->getVariants ());
112
124
$ namedArgumentVariants = $ method ->getNamedArgumentsVariants ();
113
125
$ namedArgumentVariants = $ namedArgumentVariants !== null
@@ -119,7 +131,7 @@ private function transformMethodWithStaticType(ClassReflection $declaringClass,
119
131
$ method ,
120
132
$ variants ,
121
133
$ namedArgumentVariants ,
122
- $ method -> getSelfOutType () !== null ? $ this -> transformStaticType ( $ method -> getSelfOutType ()) : null ,
134
+ $ selfOutType ,
123
135
);
124
136
}
125
137
0 commit comments