@@ -550,7 +550,13 @@ private static function parseFunction(\ReflectionFunction $ref): array
550550 $ type = new ArrayTypeNode ($ type );
551551 }
552552 $ substitutedType = self ::substituteAliases ($ type , $ aliases );
553- $ types [$ paramName ] = SpecialTypeResolver::resolve ($ substitutedType , $ ref );
553+ $ resolvedType = SpecialTypeResolver::resolve ($ substitutedType , $ ref );
554+
555+ if ($ resolvedType instanceof IdentifierTypeNode && strtolower ($ resolvedType ->name ) === 'mixed ' ) {
556+ continue ;
557+ }
558+
559+ $ types [$ paramName ] = $ resolvedType ;
554560 }
555561
556562 $ returnTag = DocblockExtractor::getReturnTag ($ phpDocNode );
@@ -696,7 +702,13 @@ private static function parseMethodHierarchyDocs(
696702 $ type = new ArrayTypeNode ($ type );
697703 }
698704 $ substitutedType = self ::substituteAliases ($ type , $ aliases );
699- $ types [$ targetParamName ] = SpecialTypeResolver::resolve ($ substitutedType , $ hierRef );
705+ $ resolvedType = SpecialTypeResolver::resolve ($ substitutedType , $ hierRef );
706+
707+ if ($ resolvedType instanceof IdentifierTypeNode && strtolower ($ resolvedType ->name ) === 'mixed ' ) {
708+ continue ;
709+ }
710+
711+ $ types [$ targetParamName ] = $ resolvedType ;
700712 }
701713 }
702714
@@ -790,15 +802,19 @@ private static function applyConstructorPromotionFallback(\ReflectionMethod $ref
790802 ) {
791803 $ propType = new ArrayTypeNode ($ propType );
792804 }
793- $ types [$ paramName ] = self ::substituteAliases ($ propType , []);
805+ $ substitutedProp = self ::substituteAliases ($ propType , []);
806+ if ($ substitutedProp instanceof IdentifierTypeNode && strtolower ($ substitutedProp ->name ) === 'mixed ' ) {
807+ continue ;
808+ }
809+ $ types [$ paramName ] = $ substitutedProp ;
794810 }
795811 }
796812 }
797813 }
798814 }
799815
800816 /**
801- * Recursively substitutes all type aliases inside a TypeNode AST.
817+ * Recursively substitutes all type aliases inside a TypeNode AST and simplifies unions/intersections containing `mixed` .
802818 *
803819 * @param array<string, TypeNode> $aliases
804820 */
@@ -864,17 +880,39 @@ public static function substituteAliases(TypeNode $node, array $aliases): TypeNo
864880 }
865881
866882 if ($ node instanceof UnionTypeNode) {
867- return new UnionTypeNode ( array_map (
883+ $ types = array_map (
868884 fn ($ t ) => self ::substituteAliases ($ t , $ aliases ),
869885 $ node ->types
870- ));
886+ );
887+
888+ foreach ($ types as $ t ) {
889+ if ($ t instanceof IdentifierTypeNode && strtolower ($ t ->name ) === 'mixed ' ) {
890+ return new IdentifierTypeNode ('mixed ' );
891+ }
892+ }
893+
894+ return new UnionTypeNode ($ types );
871895 }
872896
873897 if ($ node instanceof IntersectionTypeNode) {
874- return new IntersectionTypeNode ( array_map (
898+ $ types = array_map (
875899 fn ($ t ) => self ::substituteAliases ($ t , $ aliases ),
876900 $ node ->types
877- ));
901+ );
902+
903+ $ filtered = array_values (array_filter ($ types , function ($ t ) {
904+ return ! ($ t instanceof IdentifierTypeNode && strtolower ($ t ->name ) === 'mixed ' );
905+ }));
906+
907+ if (\count ($ filtered ) === 0 ) {
908+ return new IdentifierTypeNode ('mixed ' );
909+ }
910+
911+ if (\count ($ filtered ) === 1 ) {
912+ return $ filtered [0 ];
913+ }
914+
915+ return new IntersectionTypeNode ($ filtered );
878916 }
879917
880918 if ($ node instanceof ArrayShapeNode) {
@@ -901,4 +939,4 @@ public static function substituteAliases(TypeNode $node, array $aliases): TypeNo
901939
902940 return $ node ;
903941 }
904- }
942+ }
0 commit comments