99use PHPStan \ShouldNotHappenException ;
1010use PHPStan \TrinaryLogic ;
1111use PHPStan \Type \CallableType ;
12+ use PHPStan \Type \ConditionalType ;
13+ use PHPStan \Type \ConditionalTypeForParameter ;
1214use PHPStan \Type \Constant \ConstantIntegerType ;
15+ use PHPStan \Type \Generic \TemplateType ;
1316use PHPStan \Type \Generic \TemplateTypeMap ;
1417use PHPStan \Type \MixedType ;
1518use PHPStan \Type \NullType ;
1619use PHPStan \Type \Type ;
1720use PHPStan \Type \TypeCombinator ;
21+ use PHPStan \Type \TypeTraverser ;
1822use PHPStan \Type \UnionType ;
1923use function array_key_last ;
2024use function array_slice ;
@@ -146,6 +150,13 @@ public static function selectFromArgs(
146150 }
147151 }
148152
153+ if (count ($ parametersAcceptors ) === 1 ) {
154+ $ acceptor = $ parametersAcceptors [0 ];
155+ if (!self ::hasAcceptorTemplateOrConditionalType ($ acceptor )) {
156+ return $ acceptor ;
157+ }
158+ }
159+
149160 foreach ($ args as $ i => $ arg ) {
150161 $ type = $ scope ->getType ($ arg ->value );
151162 $ index = $ arg ->name !== null ? $ arg ->name ->toString () : $ i ;
@@ -160,6 +171,37 @@ public static function selectFromArgs(
160171 return self ::selectFromTypes ($ types , $ parametersAcceptors , $ unpack );
161172 }
162173
174+ private static function hasAcceptorTemplateOrConditionalType (ParametersAcceptor $ acceptor ): bool
175+ {
176+ if (self ::hasTemplateOrConditionalType ($ acceptor ->getReturnType ())) {
177+ return true ;
178+ }
179+
180+ foreach ($ acceptor ->getParameters () as $ parameter ) {
181+ if (!self ::hasTemplateOrConditionalType ($ parameter ->getType ())) {
182+ continue ;
183+ }
184+
185+ return true ;
186+ }
187+
188+ return false ;
189+ }
190+
191+ private static function hasTemplateOrConditionalType (Type $ type ): bool
192+ {
193+ $ has = false ;
194+ TypeTraverser::map ($ type , static function (Type $ type , callable $ traverse ) use (&$ has ): Type {
195+ if ($ type instanceof TemplateType || $ type instanceof ConditionalType || $ type instanceof ConditionalTypeForParameter) {
196+ $ has = true ;
197+ return $ type ;
198+ }
199+
200+ return $ traverse ($ type );
201+ });
202+
203+ return $ has ;
204+ }
163205 /**
164206 * @param array<int|string, Type> $types
165207 * @param ParametersAcceptor[] $parametersAcceptors
0 commit comments