1+ // ignore-tidy-filelength
12/* global addClass, getNakedUrl, getSettingValue */
23/* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */
34
@@ -80,6 +81,13 @@ const longItemTypes = [
8081const TY_GENERIC = itemTypes . indexOf ( "generic" ) ;
8182const ROOT_PATH = typeof window !== "undefined" ? window . rootPath : "../" ;
8283
84+ // Hard limit on how deep to recurse into generics when doing type-driven search.
85+ // This needs limited, partially because
86+ // a search for `Ty` shouldn't match `WithInfcx<ParamEnvAnd<Vec<ConstTy<Interner<Ty=Ty>>>>>`,
87+ // but mostly because this is the simplest and most principled way to limit the number
88+ // of permutations we need to check.
89+ const UNBOXING_LIMIT = 5 ;
90+
8391// In the search display, allows to switch between tabs.
8492function printTab ( nb ) {
8593 let iter = 0 ;
@@ -1383,10 +1391,23 @@ if (parserState.userQuery[parserState.pos] === "[") {
13831391 * @param {Map<number,number>|null } mgensIn
13841392 * - Map functions generics to query generics (never modified).
13851393 * @param {null|Map<number,number> -> bool } solutionCb - Called for each `mgens` solution.
1394+ * @param {number } unboxingDepth
1395+ * - Limit checks that Ty matches Vec<Ty>,
1396+ * but not Vec<ParamEnvAnd<WithInfcx<ConstTy<Interner<Ty=Ty>>>>>
13861397 *
13871398 * @return {boolean } - Returns true if a match, false otherwise.
13881399 */
1389- function unifyFunctionTypes ( fnTypesIn , queryElems , whereClause , mgensIn , solutionCb ) {
1400+ function unifyFunctionTypes (
1401+ fnTypesIn ,
1402+ queryElems ,
1403+ whereClause ,
1404+ mgensIn ,
1405+ solutionCb ,
1406+ unboxingDepth
1407+ ) {
1408+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1409+ return false ;
1410+ }
13901411 /**
13911412 * @type Map<integer, integer>|null
13921413 */
@@ -1405,7 +1426,7 @@ if (parserState.userQuery[parserState.pos] === "[") {
14051426 && queryElems [ 0 ] . bindings . size === 0 ) {
14061427 const queryElem = queryElems [ 0 ] ;
14071428 for ( const fnType of fnTypesIn ) {
1408- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1429+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
14091430 continue ;
14101431 }
14111432 if ( fnType . id < 0 && queryElem . id < 0 ) {
@@ -1424,7 +1445,13 @@ if (parserState.userQuery[parserState.pos] === "[") {
14241445 }
14251446 }
14261447 for ( const fnType of fnTypesIn ) {
1427- if ( ! unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1448+ if ( ! unifyFunctionTypeIsUnboxCandidate (
1449+ fnType ,
1450+ queryElem ,
1451+ whereClause ,
1452+ mgens ,
1453+ unboxingDepth + 1
1454+ ) ) {
14281455 continue ;
14291456 }
14301457 if ( fnType . id < 0 ) {
@@ -1439,7 +1466,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
14391466 queryElems ,
14401467 whereClause ,
14411468 mgensScratch ,
1442- solutionCb
1469+ solutionCb ,
1470+ unboxingDepth + 1
14431471 ) ) {
14441472 return true ;
14451473 }
@@ -1448,7 +1476,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
14481476 queryElems ,
14491477 whereClause ,
14501478 mgens ? new Map ( mgens ) : null ,
1451- solutionCb
1479+ solutionCb ,
1480+ unboxingDepth + 1
14521481 ) ) {
14531482 return true ;
14541483 }
@@ -1484,7 +1513,7 @@ if (parserState.userQuery[parserState.pos] === "[") {
14841513 let queryElemsTmp = null ;
14851514 for ( let i = flast ; i >= 0 ; i -= 1 ) {
14861515 const fnType = fnTypes [ i ] ;
1487- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1516+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
14881517 continue ;
14891518 }
14901519 let mgensScratch ;
@@ -1521,7 +1550,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
15211550 fnType ,
15221551 queryElem ,
15231552 whereClause ,
1524- mgensScratch
1553+ mgensScratch ,
1554+ unboxingDepth
15251555 ) ;
15261556 if ( ! solution ) {
15271557 return false ;
@@ -1533,14 +1563,16 @@ if (parserState.userQuery[parserState.pos] === "[") {
15331563 queryElem . generics ,
15341564 whereClause ,
15351565 simplifiedMgens ,
1536- solutionCb
1566+ solutionCb ,
1567+ unboxingDepth
15371568 ) ;
15381569 if ( passesUnification ) {
15391570 return true ;
15401571 }
15411572 }
15421573 return false ;
1543- }
1574+ } ,
1575+ unboxingDepth
15441576 ) ;
15451577 if ( passesUnification ) {
15461578 return true ;
@@ -1552,7 +1584,13 @@ if (parserState.userQuery[parserState.pos] === "[") {
15521584 }
15531585 for ( let i = flast ; i >= 0 ; i -= 1 ) {
15541586 const fnType = fnTypes [ i ] ;
1555- if ( ! unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1587+ if ( ! unifyFunctionTypeIsUnboxCandidate (
1588+ fnType ,
1589+ queryElem ,
1590+ whereClause ,
1591+ mgens ,
1592+ unboxingDepth + 1
1593+ ) ) {
15561594 continue ;
15571595 }
15581596 let mgensScratch ;
@@ -1576,7 +1614,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
15761614 queryElems ,
15771615 whereClause ,
15781616 mgensScratch ,
1579- solutionCb
1617+ solutionCb ,
1618+ unboxingDepth + 1
15801619 ) ;
15811620 if ( passesUnification ) {
15821621 return true ;
@@ -1595,11 +1634,10 @@ if (parserState.userQuery[parserState.pos] === "[") {
15951634 *
15961635 * @param {FunctionType } fnType
15971636 * @param {QueryElement } queryElem
1598- * @param {[FunctionSearchType] } whereClause - Trait bounds for generic items.
15991637 * @param {Map<number,number>|null } mgensIn - Map functions generics to query generics.
16001638 * @returns {boolean }
16011639 */
1602- function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgensIn ) {
1640+ function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgensIn ) {
16031641 // type filters look like `trait:Read` or `enum:Result`
16041642 if ( ! typePassesFilter ( queryElem . typeFilter , fnType . ty ) ) {
16051643 return false ;
@@ -1694,9 +1732,16 @@ if (parserState.userQuery[parserState.pos] === "[") {
16941732 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
16951733 * @param {Map<number,number> } mgensIn - Map functions generics to query generics.
16961734 * Never modified.
1735+ * @param {number } unboxingDepth
16971736 * @returns {false|{mgens: [Map<number,number>], simplifiedGenerics: [FunctionType]} }
16981737 */
1699- function unifyFunctionTypeCheckBindings ( fnType , queryElem , whereClause , mgensIn ) {
1738+ function unifyFunctionTypeCheckBindings (
1739+ fnType ,
1740+ queryElem ,
1741+ whereClause ,
1742+ mgensIn ,
1743+ unboxingDepth
1744+ ) {
17001745 if ( fnType . bindings . size < queryElem . bindings . size ) {
17011746 return false ;
17021747 }
@@ -1723,7 +1768,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
17231768 // return `false` makes unifyFunctionTypes return the full set of
17241769 // possible solutions
17251770 return false ;
1726- }
1771+ } ,
1772+ unboxingDepth
17271773 ) ;
17281774 return newSolutions ;
17291775 } ) ;
@@ -1753,9 +1799,19 @@ if (parserState.userQuery[parserState.pos] === "[") {
17531799 * @param {QueryElement } queryElem
17541800 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
17551801 * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1802+ * @param {number } unboxingDepth
17561803 * @returns {boolean }
17571804 */
1758- function unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) {
1805+ function unifyFunctionTypeIsUnboxCandidate (
1806+ fnType ,
1807+ queryElem ,
1808+ whereClause ,
1809+ mgens ,
1810+ unboxingDepth
1811+ ) {
1812+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1813+ return false ;
1814+ }
17591815 if ( fnType . id < 0 && queryElem . id >= 0 ) {
17601816 if ( ! whereClause ) {
17611817 return false ;
@@ -1777,14 +1833,21 @@ if (parserState.userQuery[parserState.pos] === "[") {
17771833 whereClause [ ( - fnType . id ) - 1 ] ,
17781834 queryElem ,
17791835 whereClause ,
1780- mgensTmp
1836+ mgensTmp ,
1837+ unboxingDepth
17811838 ) ;
17821839 } else if ( fnType . generics . length > 0 || fnType . bindings . size > 0 ) {
17831840 const simplifiedGenerics = [
17841841 ...fnType . generics ,
17851842 ...Array . from ( fnType . bindings . values ( ) ) . flat ( ) ,
17861843 ] ;
1787- return checkIfInList ( simplifiedGenerics , queryElem , whereClause , mgens ) ;
1844+ return checkIfInList (
1845+ simplifiedGenerics ,
1846+ queryElem ,
1847+ whereClause ,
1848+ mgens ,
1849+ unboxingDepth
1850+ ) ;
17881851 }
17891852 return false ;
17901853 }
@@ -1796,13 +1859,14 @@ if (parserState.userQuery[parserState.pos] === "[") {
17961859 * @param {Array<FunctionType> } list
17971860 * @param {QueryElement } elem - The element from the parsed query.
17981861 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
1799- * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1862+ * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1863+ * @param {number } unboxingDepth
18001864 *
18011865 * @return {boolean } - Returns true if found, false otherwise.
18021866 */
1803- function checkIfInList ( list , elem , whereClause , mgens ) {
1867+ function checkIfInList ( list , elem , whereClause , mgens , unboxingDepth ) {
18041868 for ( const entry of list ) {
1805- if ( checkType ( entry , elem , whereClause , mgens ) ) {
1869+ if ( checkType ( entry , elem , whereClause , mgens , unboxingDepth ) ) {
18061870 return true ;
18071871 }
18081872 }
@@ -1816,14 +1880,23 @@ if (parserState.userQuery[parserState.pos] === "[") {
18161880 * @param {Row } row
18171881 * @param {QueryElement } elem - The element from the parsed query.
18181882 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
1819- * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1883+ * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
18201884 *
18211885 * @return {boolean } - Returns true if the type matches, false otherwise.
18221886 */
1823- function checkType ( row , elem , whereClause , mgens ) {
1887+ function checkType ( row , elem , whereClause , mgens , unboxingDepth ) {
1888+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1889+ return false ;
1890+ }
18241891 if ( row . bindings . size === 0 && elem . bindings . size === 0 ) {
1825- if ( elem . id < 0 ) {
1826- return row . id < 0 || checkIfInList ( row . generics , elem , whereClause , mgens ) ;
1892+ if ( elem . id < 0 && mgens === null ) {
1893+ return row . id < 0 || checkIfInList (
1894+ row . generics ,
1895+ elem ,
1896+ whereClause ,
1897+ mgens ,
1898+ unboxingDepth + 1
1899+ ) ;
18271900 }
18281901 if ( row . id > 0 && elem . id > 0 && elem . pathWithoutLast . length === 0 &&
18291902 typePassesFilter ( elem . typeFilter , row . ty ) && elem . generics . length === 0 &&
@@ -1834,11 +1907,12 @@ if (parserState.userQuery[parserState.pos] === "[") {
18341907 row . generics ,
18351908 elem ,
18361909 whereClause ,
1837- mgens
1910+ mgens ,
1911+ unboxingDepth
18381912 ) ;
18391913 }
18401914 }
1841- return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens ) ;
1915+ return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens , null , unboxingDepth ) ;
18421916 }
18431917
18441918 /**
@@ -2053,9 +2127,9 @@ if (parserState.userQuery[parserState.pos] === "[") {
20532127 ) ;
20542128 if ( tfpDist !== null ) {
20552129 const in_args = row . type && row . type . inputs
2056- && checkIfInList ( row . type . inputs , elem , row . type . where_clause ) ;
2130+ && checkIfInList ( row . type . inputs , elem , row . type . where_clause , null , 0 ) ;
20572131 const returned = row . type && row . type . output
2058- && checkIfInList ( row . type . output , elem , row . type . where_clause ) ;
2132+ && checkIfInList ( row . type . output , elem , row . type . where_clause , null , 0 ) ;
20592133 if ( in_args ) {
20602134 results_in_args . max_dist = Math . max ( results_in_args . max_dist || 0 , tfpDist ) ;
20612135 const maxDist = results_in_args . size < MAX_RESULTS ?
@@ -2141,9 +2215,12 @@ if (parserState.userQuery[parserState.pos] === "[") {
21412215 row . type . output ,
21422216 parsedQuery . returned ,
21432217 row . type . where_clause ,
2144- mgens
2218+ mgens ,
2219+ null ,
2220+ 0 // unboxing depth
21452221 ) ;
2146- }
2222+ } ,
2223+ 0 // unboxing depth
21472224 ) ) {
21482225 return ;
21492226 }
0 commit comments