@@ -81,6 +81,13 @@ const longItemTypes = [
8181const TY_GENERIC = itemTypes . indexOf ( "generic" ) ;
8282const ROOT_PATH = typeof window !== "undefined" ? window . rootPath : "../" ;
8383
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+
8491// In the search display, allows to switch between tabs.
8592function printTab ( nb ) {
8693 let iter = 0 ;
@@ -1458,10 +1465,23 @@ function initSearch(rawSearchIndex) {
14581465 * @param {Map<number,number>|null } mgensIn
14591466 * - Map functions generics to query generics (never modified).
14601467 * @param {null|Map<number,number> -> bool } solutionCb - Called for each `mgens` solution.
1468+ * @param {number } unboxingDepth
1469+ * - Limit checks that Ty matches Vec<Ty>,
1470+ * but not Vec<ParamEnvAnd<WithInfcx<ConstTy<Interner<Ty=Ty>>>>>
14611471 *
14621472 * @return {boolean } - Returns true if a match, false otherwise.
14631473 */
1464- function unifyFunctionTypes ( fnTypesIn , queryElems , whereClause , mgensIn , solutionCb ) {
1474+ function unifyFunctionTypes (
1475+ fnTypesIn ,
1476+ queryElems ,
1477+ whereClause ,
1478+ mgensIn ,
1479+ solutionCb ,
1480+ unboxingDepth
1481+ ) {
1482+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1483+ return false ;
1484+ }
14651485 /**
14661486 * @type Map<integer, integer>|null
14671487 */
@@ -1480,7 +1500,7 @@ function initSearch(rawSearchIndex) {
14801500 && queryElems [ 0 ] . bindings . size === 0 ) {
14811501 const queryElem = queryElems [ 0 ] ;
14821502 for ( const fnType of fnTypesIn ) {
1483- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1503+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
14841504 continue ;
14851505 }
14861506 if ( fnType . id < 0 && queryElem . id < 0 ) {
@@ -1499,7 +1519,13 @@ function initSearch(rawSearchIndex) {
14991519 }
15001520 }
15011521 for ( const fnType of fnTypesIn ) {
1502- if ( ! unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1522+ if ( ! unifyFunctionTypeIsUnboxCandidate (
1523+ fnType ,
1524+ queryElem ,
1525+ whereClause ,
1526+ mgens ,
1527+ unboxingDepth + 1
1528+ ) ) {
15031529 continue ;
15041530 }
15051531 if ( fnType . id < 0 ) {
@@ -1514,7 +1540,8 @@ function initSearch(rawSearchIndex) {
15141540 queryElems ,
15151541 whereClause ,
15161542 mgensScratch ,
1517- solutionCb
1543+ solutionCb ,
1544+ unboxingDepth + 1
15181545 ) ) {
15191546 return true ;
15201547 }
@@ -1523,7 +1550,8 @@ function initSearch(rawSearchIndex) {
15231550 queryElems ,
15241551 whereClause ,
15251552 mgens ? new Map ( mgens ) : null ,
1526- solutionCb
1553+ solutionCb ,
1554+ unboxingDepth + 1
15271555 ) ) {
15281556 return true ;
15291557 }
@@ -1559,7 +1587,7 @@ function initSearch(rawSearchIndex) {
15591587 let queryElemsTmp = null ;
15601588 for ( let i = flast ; i >= 0 ; i -= 1 ) {
15611589 const fnType = fnTypes [ i ] ;
1562- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1590+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
15631591 continue ;
15641592 }
15651593 let mgensScratch ;
@@ -1596,7 +1624,8 @@ function initSearch(rawSearchIndex) {
15961624 fnType ,
15971625 queryElem ,
15981626 whereClause ,
1599- mgensScratch
1627+ mgensScratch ,
1628+ unboxingDepth
16001629 ) ;
16011630 if ( ! solution ) {
16021631 return false ;
@@ -1608,14 +1637,16 @@ function initSearch(rawSearchIndex) {
16081637 queryElem . generics ,
16091638 whereClause ,
16101639 simplifiedMgens ,
1611- solutionCb
1640+ solutionCb ,
1641+ unboxingDepth
16121642 ) ;
16131643 if ( passesUnification ) {
16141644 return true ;
16151645 }
16161646 }
16171647 return false ;
1618- }
1648+ } ,
1649+ unboxingDepth
16191650 ) ;
16201651 if ( passesUnification ) {
16211652 return true ;
@@ -1627,7 +1658,13 @@ function initSearch(rawSearchIndex) {
16271658 }
16281659 for ( let i = flast ; i >= 0 ; i -= 1 ) {
16291660 const fnType = fnTypes [ i ] ;
1630- if ( ! unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1661+ if ( ! unifyFunctionTypeIsUnboxCandidate (
1662+ fnType ,
1663+ queryElem ,
1664+ whereClause ,
1665+ mgens ,
1666+ unboxingDepth + 1
1667+ ) ) {
16311668 continue ;
16321669 }
16331670 let mgensScratch ;
@@ -1651,7 +1688,8 @@ function initSearch(rawSearchIndex) {
16511688 queryElems ,
16521689 whereClause ,
16531690 mgensScratch ,
1654- solutionCb
1691+ solutionCb ,
1692+ unboxingDepth + 1
16551693 ) ;
16561694 if ( passesUnification ) {
16571695 return true ;
@@ -1670,11 +1708,10 @@ function initSearch(rawSearchIndex) {
16701708 *
16711709 * @param {FunctionType } fnType
16721710 * @param {QueryElement } queryElem
1673- * @param {[FunctionSearchType] } whereClause - Trait bounds for generic items.
16741711 * @param {Map<number,number>|null } mgensIn - Map functions generics to query generics.
16751712 * @returns {boolean }
16761713 */
1677- function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgensIn ) {
1714+ function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgensIn ) {
16781715 // type filters look like `trait:Read` or `enum:Result`
16791716 if ( ! typePassesFilter ( queryElem . typeFilter , fnType . ty ) ) {
16801717 return false ;
@@ -1775,9 +1812,16 @@ function initSearch(rawSearchIndex) {
17751812 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
17761813 * @param {Map<number,number> } mgensIn - Map functions generics to query generics.
17771814 * Never modified.
1815+ * @param {number } unboxingDepth
17781816 * @returns {false|{mgens: [Map<number,number>], simplifiedGenerics: [FunctionType]} }
17791817 */
1780- function unifyFunctionTypeCheckBindings ( fnType , queryElem , whereClause , mgensIn ) {
1818+ function unifyFunctionTypeCheckBindings (
1819+ fnType ,
1820+ queryElem ,
1821+ whereClause ,
1822+ mgensIn ,
1823+ unboxingDepth
1824+ ) {
17811825 if ( fnType . bindings . size < queryElem . bindings . size ) {
17821826 return false ;
17831827 }
@@ -1804,7 +1848,8 @@ function initSearch(rawSearchIndex) {
18041848 // return `false` makes unifyFunctionTypes return the full set of
18051849 // possible solutions
18061850 return false ;
1807- }
1851+ } ,
1852+ unboxingDepth
18081853 ) ;
18091854 return newSolutions ;
18101855 } ) ;
@@ -1834,9 +1879,19 @@ function initSearch(rawSearchIndex) {
18341879 * @param {QueryElement } queryElem
18351880 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
18361881 * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1882+ * @param {number } unboxingDepth
18371883 * @returns {boolean }
18381884 */
1839- function unifyFunctionTypeIsUnboxCandidate ( fnType , queryElem , whereClause , mgens ) {
1885+ function unifyFunctionTypeIsUnboxCandidate (
1886+ fnType ,
1887+ queryElem ,
1888+ whereClause ,
1889+ mgens ,
1890+ unboxingDepth
1891+ ) {
1892+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1893+ return false ;
1894+ }
18401895 if ( fnType . id < 0 && queryElem . id >= 0 ) {
18411896 if ( ! whereClause ) {
18421897 return false ;
@@ -1858,14 +1913,21 @@ function initSearch(rawSearchIndex) {
18581913 whereClause [ ( - fnType . id ) - 1 ] ,
18591914 queryElem ,
18601915 whereClause ,
1861- mgensTmp
1916+ mgensTmp ,
1917+ unboxingDepth
18621918 ) ;
18631919 } else if ( fnType . generics . length > 0 || fnType . bindings . size > 0 ) {
18641920 const simplifiedGenerics = [
18651921 ...fnType . generics ,
18661922 ...Array . from ( fnType . bindings . values ( ) ) . flat ( ) ,
18671923 ] ;
1868- return checkIfInList ( simplifiedGenerics , queryElem , whereClause , mgens ) ;
1924+ return checkIfInList (
1925+ simplifiedGenerics ,
1926+ queryElem ,
1927+ whereClause ,
1928+ mgens ,
1929+ unboxingDepth
1930+ ) ;
18691931 }
18701932 return false ;
18711933 }
@@ -1877,13 +1939,14 @@ function initSearch(rawSearchIndex) {
18771939 * @param {Array<FunctionType> } list
18781940 * @param {QueryElement } elem - The element from the parsed query.
18791941 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
1880- * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1942+ * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1943+ * @param {number } unboxingDepth
18811944 *
18821945 * @return {boolean } - Returns true if found, false otherwise.
18831946 */
1884- function checkIfInList ( list , elem , whereClause , mgens ) {
1947+ function checkIfInList ( list , elem , whereClause , mgens , unboxingDepth ) {
18851948 for ( const entry of list ) {
1886- if ( checkType ( entry , elem , whereClause , mgens ) ) {
1949+ if ( checkType ( entry , elem , whereClause , mgens , unboxingDepth ) ) {
18871950 return true ;
18881951 }
18891952 }
@@ -1897,14 +1960,23 @@ function initSearch(rawSearchIndex) {
18971960 * @param {Row } row
18981961 * @param {QueryElement } elem - The element from the parsed query.
18991962 * @param {[FunctionType] } whereClause - Trait bounds for generic items.
1900- * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1963+ * @param {Map<number,number>|null } mgens - Map functions generics to query generics.
19011964 *
19021965 * @return {boolean } - Returns true if the type matches, false otherwise.
19031966 */
1904- function checkType ( row , elem , whereClause , mgens ) {
1967+ function checkType ( row , elem , whereClause , mgens , unboxingDepth ) {
1968+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1969+ return false ;
1970+ }
19051971 if ( row . bindings . size === 0 && elem . bindings . size === 0 ) {
1906- if ( elem . id < 0 ) {
1907- return row . id < 0 || checkIfInList ( row . generics , elem , whereClause , mgens ) ;
1972+ if ( elem . id < 0 && mgens === null ) {
1973+ return row . id < 0 || checkIfInList (
1974+ row . generics ,
1975+ elem ,
1976+ whereClause ,
1977+ mgens ,
1978+ unboxingDepth + 1
1979+ ) ;
19081980 }
19091981 if ( row . id > 0 && elem . id > 0 && elem . pathWithoutLast . length === 0 &&
19101982 typePassesFilter ( elem . typeFilter , row . ty ) && elem . generics . length === 0 &&
@@ -1916,11 +1988,12 @@ function initSearch(rawSearchIndex) {
19161988 row . generics ,
19171989 elem ,
19181990 whereClause ,
1919- mgens
1991+ mgens ,
1992+ unboxingDepth
19201993 ) ;
19211994 }
19221995 }
1923- return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens ) ;
1996+ return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens , null , unboxingDepth ) ;
19241997 }
19251998
19261999 /**
@@ -2135,9 +2208,9 @@ function initSearch(rawSearchIndex) {
21352208 ) ;
21362209 if ( tfpDist !== null ) {
21372210 const in_args = row . type && row . type . inputs
2138- && checkIfInList ( row . type . inputs , elem , row . type . where_clause ) ;
2211+ && checkIfInList ( row . type . inputs , elem , row . type . where_clause , null , 0 ) ;
21392212 const returned = row . type && row . type . output
2140- && checkIfInList ( row . type . output , elem , row . type . where_clause ) ;
2213+ && checkIfInList ( row . type . output , elem , row . type . where_clause , null , 0 ) ;
21412214 if ( in_args ) {
21422215 results_in_args . max_dist = Math . max ( results_in_args . max_dist || 0 , tfpDist ) ;
21432216 const maxDist = results_in_args . size < MAX_RESULTS ?
@@ -2223,9 +2296,12 @@ function initSearch(rawSearchIndex) {
22232296 row . type . output ,
22242297 parsedQuery . returned ,
22252298 row . type . where_clause ,
2226- mgens
2299+ mgens ,
2300+ null ,
2301+ 0 // unboxing depth
22272302 ) ;
2228- }
2303+ } ,
2304+ 0 // unboxing depth
22292305 ) ) {
22302306 return ;
22312307 }
0 commit comments