1
+ // ignore-tidy-filelength
1
2
/* global addClass, getNakedUrl, getSettingValue */
2
3
/* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */
3
4
@@ -80,6 +81,13 @@ const longItemTypes = [
80
81
const TY_GENERIC = itemTypes . indexOf ( "generic" ) ;
81
82
const ROOT_PATH = typeof window !== "undefined" ? window . rootPath : "../" ;
82
83
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
+
83
91
// In the search display, allows to switch between tabs.
84
92
function printTab ( nb ) {
85
93
let iter = 0 ;
@@ -1383,10 +1391,23 @@ if (parserState.userQuery[parserState.pos] === "[") {
1383
1391
* @param {Map<number,number>|null } mgensIn
1384
1392
* - Map functions generics to query generics (never modified).
1385
1393
* @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>>>>>
1386
1397
*
1387
1398
* @return {boolean } - Returns true if a match, false otherwise.
1388
1399
*/
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
+ }
1390
1411
/**
1391
1412
* @type Map<integer, integer>|null
1392
1413
*/
@@ -1405,7 +1426,7 @@ if (parserState.userQuery[parserState.pos] === "[") {
1405
1426
&& queryElems [ 0 ] . bindings . size === 0 ) {
1406
1427
const queryElem = queryElems [ 0 ] ;
1407
1428
for ( const fnType of fnTypesIn ) {
1408
- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1429
+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
1409
1430
continue ;
1410
1431
}
1411
1432
if ( fnType . id < 0 && queryElem . id < 0 ) {
@@ -1424,7 +1445,13 @@ if (parserState.userQuery[parserState.pos] === "[") {
1424
1445
}
1425
1446
}
1426
1447
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
+ ) ) {
1428
1455
continue ;
1429
1456
}
1430
1457
if ( fnType . id < 0 ) {
@@ -1439,7 +1466,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
1439
1466
queryElems ,
1440
1467
whereClause ,
1441
1468
mgensScratch ,
1442
- solutionCb
1469
+ solutionCb ,
1470
+ unboxingDepth + 1
1443
1471
) ) {
1444
1472
return true ;
1445
1473
}
@@ -1448,7 +1476,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
1448
1476
queryElems ,
1449
1477
whereClause ,
1450
1478
mgens ? new Map ( mgens ) : null ,
1451
- solutionCb
1479
+ solutionCb ,
1480
+ unboxingDepth + 1
1452
1481
) ) {
1453
1482
return true ;
1454
1483
}
@@ -1484,7 +1513,7 @@ if (parserState.userQuery[parserState.pos] === "[") {
1484
1513
let queryElemsTmp = null ;
1485
1514
for ( let i = flast ; i >= 0 ; i -= 1 ) {
1486
1515
const fnType = fnTypes [ i ] ;
1487
- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1516
+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
1488
1517
continue ;
1489
1518
}
1490
1519
let mgensScratch ;
@@ -1521,7 +1550,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
1521
1550
fnType ,
1522
1551
queryElem ,
1523
1552
whereClause ,
1524
- mgensScratch
1553
+ mgensScratch ,
1554
+ unboxingDepth
1525
1555
) ;
1526
1556
if ( ! solution ) {
1527
1557
return false ;
@@ -1533,14 +1563,16 @@ if (parserState.userQuery[parserState.pos] === "[") {
1533
1563
queryElem . generics ,
1534
1564
whereClause ,
1535
1565
simplifiedMgens ,
1536
- solutionCb
1566
+ solutionCb ,
1567
+ unboxingDepth
1537
1568
) ;
1538
1569
if ( passesUnification ) {
1539
1570
return true ;
1540
1571
}
1541
1572
}
1542
1573
return false ;
1543
- }
1574
+ } ,
1575
+ unboxingDepth
1544
1576
) ;
1545
1577
if ( passesUnification ) {
1546
1578
return true ;
@@ -1552,7 +1584,13 @@ if (parserState.userQuery[parserState.pos] === "[") {
1552
1584
}
1553
1585
for ( let i = flast ; i >= 0 ; i -= 1 ) {
1554
1586
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
+ ) ) {
1556
1594
continue ;
1557
1595
}
1558
1596
let mgensScratch ;
@@ -1576,7 +1614,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
1576
1614
queryElems ,
1577
1615
whereClause ,
1578
1616
mgensScratch ,
1579
- solutionCb
1617
+ solutionCb ,
1618
+ unboxingDepth + 1
1580
1619
) ;
1581
1620
if ( passesUnification ) {
1582
1621
return true ;
@@ -1595,11 +1634,10 @@ if (parserState.userQuery[parserState.pos] === "[") {
1595
1634
*
1596
1635
* @param {FunctionType } fnType
1597
1636
* @param {QueryElement } queryElem
1598
- * @param {[FunctionSearchType] } whereClause - Trait bounds for generic items.
1599
1637
* @param {Map<number,number>|null } mgensIn - Map functions generics to query generics.
1600
1638
* @returns {boolean }
1601
1639
*/
1602
- function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgensIn ) {
1640
+ function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgensIn ) {
1603
1641
// type filters look like `trait:Read` or `enum:Result`
1604
1642
if ( ! typePassesFilter ( queryElem . typeFilter , fnType . ty ) ) {
1605
1643
return false ;
@@ -1694,9 +1732,16 @@ if (parserState.userQuery[parserState.pos] === "[") {
1694
1732
* @param {[FunctionType] } whereClause - Trait bounds for generic items.
1695
1733
* @param {Map<number,number> } mgensIn - Map functions generics to query generics.
1696
1734
* Never modified.
1735
+ * @param {number } unboxingDepth
1697
1736
* @returns {false|{mgens: [Map<number,number>], simplifiedGenerics: [FunctionType]} }
1698
1737
*/
1699
- function unifyFunctionTypeCheckBindings ( fnType , queryElem , whereClause , mgensIn ) {
1738
+ function unifyFunctionTypeCheckBindings (
1739
+ fnType ,
1740
+ queryElem ,
1741
+ whereClause ,
1742
+ mgensIn ,
1743
+ unboxingDepth
1744
+ ) {
1700
1745
if ( fnType . bindings . size < queryElem . bindings . size ) {
1701
1746
return false ;
1702
1747
}
@@ -1723,7 +1768,8 @@ if (parserState.userQuery[parserState.pos] === "[") {
1723
1768
// return `false` makes unifyFunctionTypes return the full set of
1724
1769
// possible solutions
1725
1770
return false ;
1726
- }
1771
+ } ,
1772
+ unboxingDepth
1727
1773
) ;
1728
1774
return newSolutions ;
1729
1775
} ) ;
@@ -1753,9 +1799,19 @@ if (parserState.userQuery[parserState.pos] === "[") {
1753
1799
* @param {QueryElement } queryElem
1754
1800
* @param {[FunctionType] } whereClause - Trait bounds for generic items.
1755
1801
* @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1802
+ * @param {number } unboxingDepth
1756
1803
* @returns {boolean }
1757
1804
*/
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
+ }
1759
1815
if ( fnType . id < 0 && queryElem . id >= 0 ) {
1760
1816
if ( ! whereClause ) {
1761
1817
return false ;
@@ -1777,14 +1833,21 @@ if (parserState.userQuery[parserState.pos] === "[") {
1777
1833
whereClause [ ( - fnType . id ) - 1 ] ,
1778
1834
queryElem ,
1779
1835
whereClause ,
1780
- mgensTmp
1836
+ mgensTmp ,
1837
+ unboxingDepth
1781
1838
) ;
1782
1839
} else if ( fnType . generics . length > 0 || fnType . bindings . size > 0 ) {
1783
1840
const simplifiedGenerics = [
1784
1841
...fnType . generics ,
1785
1842
...Array . from ( fnType . bindings . values ( ) ) . flat ( ) ,
1786
1843
] ;
1787
- return checkIfInList ( simplifiedGenerics , queryElem , whereClause , mgens ) ;
1844
+ return checkIfInList (
1845
+ simplifiedGenerics ,
1846
+ queryElem ,
1847
+ whereClause ,
1848
+ mgens ,
1849
+ unboxingDepth
1850
+ ) ;
1788
1851
}
1789
1852
return false ;
1790
1853
}
@@ -1796,13 +1859,14 @@ if (parserState.userQuery[parserState.pos] === "[") {
1796
1859
* @param {Array<FunctionType> } list
1797
1860
* @param {QueryElement } elem - The element from the parsed query.
1798
1861
* @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
1800
1864
*
1801
1865
* @return {boolean } - Returns true if found, false otherwise.
1802
1866
*/
1803
- function checkIfInList ( list , elem , whereClause , mgens ) {
1867
+ function checkIfInList ( list , elem , whereClause , mgens , unboxingDepth ) {
1804
1868
for ( const entry of list ) {
1805
- if ( checkType ( entry , elem , whereClause , mgens ) ) {
1869
+ if ( checkType ( entry , elem , whereClause , mgens , unboxingDepth ) ) {
1806
1870
return true ;
1807
1871
}
1808
1872
}
@@ -1816,14 +1880,23 @@ if (parserState.userQuery[parserState.pos] === "[") {
1816
1880
* @param {Row } row
1817
1881
* @param {QueryElement } elem - The element from the parsed query.
1818
1882
* @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.
1820
1884
*
1821
1885
* @return {boolean } - Returns true if the type matches, false otherwise.
1822
1886
*/
1823
- function checkType ( row , elem , whereClause , mgens ) {
1887
+ function checkType ( row , elem , whereClause , mgens , unboxingDepth ) {
1888
+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1889
+ return false ;
1890
+ }
1824
1891
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
+ ) ;
1827
1900
}
1828
1901
if ( row . id > 0 && elem . id > 0 && elem . pathWithoutLast . length === 0 &&
1829
1902
typePassesFilter ( elem . typeFilter , row . ty ) && elem . generics . length === 0 &&
@@ -1834,11 +1907,12 @@ if (parserState.userQuery[parserState.pos] === "[") {
1834
1907
row . generics ,
1835
1908
elem ,
1836
1909
whereClause ,
1837
- mgens
1910
+ mgens ,
1911
+ unboxingDepth
1838
1912
) ;
1839
1913
}
1840
1914
}
1841
- return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens ) ;
1915
+ return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens , null , unboxingDepth ) ;
1842
1916
}
1843
1917
1844
1918
/**
@@ -2053,9 +2127,9 @@ if (parserState.userQuery[parserState.pos] === "[") {
2053
2127
) ;
2054
2128
if ( tfpDist !== null ) {
2055
2129
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 ) ;
2057
2131
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 ) ;
2059
2133
if ( in_args ) {
2060
2134
results_in_args . max_dist = Math . max ( results_in_args . max_dist || 0 , tfpDist ) ;
2061
2135
const maxDist = results_in_args . size < MAX_RESULTS ?
@@ -2141,9 +2215,12 @@ if (parserState.userQuery[parserState.pos] === "[") {
2141
2215
row . type . output ,
2142
2216
parsedQuery . returned ,
2143
2217
row . type . where_clause ,
2144
- mgens
2218
+ mgens ,
2219
+ null ,
2220
+ 0 // unboxing depth
2145
2221
) ;
2146
- }
2222
+ } ,
2223
+ 0 // unboxing depth
2147
2224
) ) {
2148
2225
return ;
2149
2226
}
0 commit comments