@@ -94,6 +94,9 @@ class ConstantArrayType implements Type
9494
9595 private ?Type $ iterableValueType = null ;
9696
97+ /** @var array<int|string, int>|null */
98+ private ?array $ keyIndexMap = null ;
99+
97100 /**
98101 * @api
99102 * @param list<ConstantIntegerType|ConstantStringType> $keyTypes
@@ -1805,15 +1808,17 @@ public function isKeysSupersetOf(self $otherArray): bool
18051808
18061809 $ failOnDifferentValueType = $ keyTypesCount !== $ otherKeyTypesCount || $ keyTypesCount < 2 ;
18071810
1808- $ keyTypes = $ this ->keyTypes ;
1811+ $ keyIndexMap = $ this ->getKeyIndexMap ();
1812+ $ otherKeyValues = [];
18091813
18101814 foreach ($ otherArray ->keyTypes as $ j => $ keyType ) {
1811- $ i = self ::findKeyIndex ($ keyType , $ keyTypes );
1815+ $ keyValue = $ keyType ->getValue ();
1816+ $ i = $ keyIndexMap [$ keyValue ] ?? null ;
18121817 if ($ i === null ) {
18131818 return false ;
18141819 }
18151820
1816- unset( $ keyTypes [ $ i ]) ;
1821+ $ otherKeyValues [ $ keyValue ] = true ;
18171822
18181823 $ valueType = $ this ->valueTypes [$ i ];
18191824 $ otherValueType = $ otherArray ->valueTypes [$ j ];
@@ -1828,7 +1833,10 @@ public function isKeysSupersetOf(self $otherArray): bool
18281833 }
18291834
18301835 $ requiredKeyCount = 0 ;
1831- foreach (array_keys ($ keyTypes ) as $ i ) {
1836+ foreach ($ this ->keyTypes as $ i => $ keyType ) {
1837+ if (isset ($ otherKeyValues [$ keyType ->getValue ()])) {
1838+ continue ;
1839+ }
18321840 if ($ this ->isOptionalKey ($ i )) {
18331841 continue ;
18341842 }
@@ -1868,12 +1876,29 @@ public function mergeWith(self $otherArray): self
18681876 return $ this ->recreate ($ this ->keyTypes , $ valueTypes , $ nextAutoIndexes , $ optionalKeys , $ this ->isList ->and ($ otherArray ->isList ));
18691877 }
18701878
1879+ /**
1880+ * @return array<int|string, int>
1881+ */
1882+ private function getKeyIndexMap (): array
1883+ {
1884+ if ($ this ->keyIndexMap !== null ) {
1885+ return $ this ->keyIndexMap ;
1886+ }
1887+
1888+ $ map = [];
1889+ foreach ($ this ->keyTypes as $ i => $ keyType ) {
1890+ $ map [$ keyType ->getValue ()] = $ i ;
1891+ }
1892+
1893+ return $ this ->keyIndexMap = $ map ;
1894+ }
1895+
18711896 /**
18721897 * @param ConstantIntegerType|ConstantStringType $otherKeyType
18731898 */
18741899 private function getKeyIndex ($ otherKeyType ): ?int
18751900 {
1876- return self :: findKeyIndex ( $ otherKeyType, $ this -> keyTypes ) ;
1901+ return $ this -> getKeyIndexMap ()[ $ otherKeyType-> getValue ()] ?? null ;
18771902 }
18781903
18791904 /**
0 commit comments