6
6
use PHPStan \Analyser \Scope ;
7
7
use PHPStan \DependencyInjection \AutowiredParameter ;
8
8
use PHPStan \DependencyInjection \AutowiredService ;
9
+ use PHPStan \Reflection \ParametersAcceptor ;
9
10
use PHPStan \Reflection \ReflectionProvider ;
10
11
use PHPStan \Type \BenevolentUnionType ;
11
12
use PHPStan \Type \CallableType ;
16
17
use PHPStan \Type \MixedType ;
17
18
use PHPStan \Type \NeverType ;
18
19
use PHPStan \Type \NullType ;
20
+ use PHPStan \Type \SimultaneousTypeTraverser ;
19
21
use PHPStan \Type \StrictMixedType ;
20
22
use PHPStan \Type \Type ;
21
23
use PHPStan \Type \TypeCombinator ;
@@ -84,18 +86,21 @@ private function transformCommonType(Type $type): Type
84
86
/**
85
87
* @return array{Type, bool}
86
88
*/
87
- private function transformAcceptedType (Type $ acceptingType , Type $ acceptedType ): array
89
+ private function transformAcceptedType (Type $ acceptingType , Type $ acceptedType, bool $ strictTypes ): array
88
90
{
89
91
$ checkForUnion = $ this ->checkUnionTypes ;
90
- $ acceptedType = TypeTraverser ::map ($ acceptedType , function (Type $ acceptedType , callable $ traverse ) use ($ acceptingType , & $ checkForUnion ): Type {
92
+ $ acceptedType = SimultaneousTypeTraverser ::map ($ acceptedType , $ acceptingType , function (Type $ acceptedType , Type $ acceptingType , callable $ traverse ) use (& $ checkForUnion , $ strictTypes ): Type {
91
93
if ($ acceptedType instanceof CallableType) {
92
94
if ($ acceptedType ->isCommonCallable ()) {
93
95
return $ acceptedType ;
94
96
}
97
+ if (!$ acceptingType instanceof ParametersAcceptor) {
98
+ return $ acceptedType ;
99
+ }
95
100
96
101
return new CallableType (
97
102
$ acceptedType ->getParameters (),
98
- $ traverse ($ this ->transformCommonType ($ acceptedType ->getReturnType ())),
103
+ $ traverse ($ this ->transformCommonType ($ acceptedType ->getReturnType ()), $ acceptingType -> getReturnType () ),
99
104
$ acceptedType ->isVariadic (),
100
105
$ acceptedType ->getTemplateTypeMap (),
101
106
$ acceptedType ->getResolvedTemplateTypeMap (),
@@ -109,9 +114,13 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
109
114
return $ acceptedType ;
110
115
}
111
116
117
+ if (!$ acceptingType instanceof ParametersAcceptor) {
118
+ return $ acceptedType ;
119
+ }
120
+
112
121
return new ClosureType (
113
122
$ acceptedType ->getParameters (),
114
- $ traverse ($ this ->transformCommonType ($ acceptedType ->getReturnType ())),
123
+ $ traverse ($ this ->transformCommonType ($ acceptedType ->getReturnType ()), $ acceptingType -> getReturnType () ),
115
124
$ acceptedType ->isVariadic (),
116
125
$ acceptedType ->getTemplateTypeMap (),
117
126
$ acceptedType ->getResolvedTemplateTypeMap (),
@@ -127,21 +136,22 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
127
136
128
137
if (
129
138
!$ this ->checkNullables
130
- && !$ acceptingType instanceof NullType
131
- && !$ acceptedType instanceof NullType
132
139
&& !$ acceptedType instanceof BenevolentUnionType
140
+ && !$ acceptedType instanceof NullType
141
+ && TypeCombinator::containsNull ($ acceptedType )
142
+ && !TypeCombinator::containsNull ($ acceptingType )
133
143
) {
134
- return $ traverse (TypeCombinator::removeNull ($ acceptedType ));
144
+ return $ traverse (TypeCombinator::removeNull ($ acceptedType ), $ acceptingType );
135
145
}
136
146
137
147
if ($ this ->checkBenevolentUnionTypes ) {
138
148
if ($ acceptedType instanceof BenevolentUnionType) {
139
149
$ checkForUnion = true ;
140
- return $ traverse (TypeUtils::toStrictUnion ($ acceptedType ));
150
+ return $ traverse (TypeUtils::toStrictUnion ($ acceptedType ), $ acceptingType );
141
151
}
142
152
}
143
153
144
- return $ traverse ($ this ->transformCommonType ($ acceptedType ));
154
+ return $ traverse ($ this ->transformCommonType ($ acceptedType ), $ acceptingType );
145
155
});
146
156
147
157
return [$ acceptedType , $ checkForUnion ];
@@ -150,7 +160,7 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType):
150
160
/** @api */
151
161
public function accepts (Type $ acceptingType , Type $ acceptedType , bool $ strictTypes ): RuleLevelHelperAcceptsResult
152
162
{
153
- [$ acceptedType , $ checkForUnion ] = $ this ->transformAcceptedType ($ acceptingType , $ acceptedType );
163
+ [$ acceptedType , $ checkForUnion ] = $ this ->transformAcceptedType ($ acceptingType , $ acceptedType, $ strictTypes );
154
164
$ acceptingType = $ this ->transformCommonType ($ acceptingType );
155
165
156
166
$ accepts = $ acceptingType ->accepts ($ acceptedType , $ strictTypes );
0 commit comments