@@ -81,6 +81,13 @@ const longItemTypes = [
81
81
const TY_GENERIC = itemTypes . indexOf ( "generic" ) ;
82
82
const ROOT_PATH = typeof window !== "undefined" ? window . rootPath : "../" ;
83
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
+
84
91
// In the search display, allows to switch between tabs.
85
92
function printTab ( nb ) {
86
93
let iter = 0 ;
@@ -1458,10 +1465,23 @@ function initSearch(rawSearchIndex) {
1458
1465
* @param {Map<number,number>|null } mgensIn
1459
1466
* - Map functions generics to query generics (never modified).
1460
1467
* @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>>>>>
1461
1471
*
1462
1472
* @return {boolean } - Returns true if a match, false otherwise.
1463
1473
*/
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
+ }
1465
1485
/**
1466
1486
* @type Map<integer, integer>|null
1467
1487
*/
@@ -1480,7 +1500,7 @@ function initSearch(rawSearchIndex) {
1480
1500
&& queryElems [ 0 ] . bindings . size === 0 ) {
1481
1501
const queryElem = queryElems [ 0 ] ;
1482
1502
for ( const fnType of fnTypesIn ) {
1483
- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1503
+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
1484
1504
continue ;
1485
1505
}
1486
1506
if ( fnType . id < 0 && queryElem . id < 0 ) {
@@ -1499,7 +1519,13 @@ function initSearch(rawSearchIndex) {
1499
1519
}
1500
1520
}
1501
1521
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
+ ) ) {
1503
1529
continue ;
1504
1530
}
1505
1531
if ( fnType . id < 0 ) {
@@ -1514,7 +1540,8 @@ function initSearch(rawSearchIndex) {
1514
1540
queryElems ,
1515
1541
whereClause ,
1516
1542
mgensScratch ,
1517
- solutionCb
1543
+ solutionCb ,
1544
+ unboxingDepth + 1
1518
1545
) ) {
1519
1546
return true ;
1520
1547
}
@@ -1523,7 +1550,8 @@ function initSearch(rawSearchIndex) {
1523
1550
queryElems ,
1524
1551
whereClause ,
1525
1552
mgens ? new Map ( mgens ) : null ,
1526
- solutionCb
1553
+ solutionCb ,
1554
+ unboxingDepth + 1
1527
1555
) ) {
1528
1556
return true ;
1529
1557
}
@@ -1559,7 +1587,7 @@ function initSearch(rawSearchIndex) {
1559
1587
let queryElemsTmp = null ;
1560
1588
for ( let i = flast ; i >= 0 ; i -= 1 ) {
1561
1589
const fnType = fnTypes [ i ] ;
1562
- if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgens ) ) {
1590
+ if ( ! unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgens ) ) {
1563
1591
continue ;
1564
1592
}
1565
1593
let mgensScratch ;
@@ -1596,7 +1624,8 @@ function initSearch(rawSearchIndex) {
1596
1624
fnType ,
1597
1625
queryElem ,
1598
1626
whereClause ,
1599
- mgensScratch
1627
+ mgensScratch ,
1628
+ unboxingDepth
1600
1629
) ;
1601
1630
if ( ! solution ) {
1602
1631
return false ;
@@ -1608,14 +1637,16 @@ function initSearch(rawSearchIndex) {
1608
1637
queryElem . generics ,
1609
1638
whereClause ,
1610
1639
simplifiedMgens ,
1611
- solutionCb
1640
+ solutionCb ,
1641
+ unboxingDepth
1612
1642
) ;
1613
1643
if ( passesUnification ) {
1614
1644
return true ;
1615
1645
}
1616
1646
}
1617
1647
return false ;
1618
- }
1648
+ } ,
1649
+ unboxingDepth
1619
1650
) ;
1620
1651
if ( passesUnification ) {
1621
1652
return true ;
@@ -1627,7 +1658,13 @@ function initSearch(rawSearchIndex) {
1627
1658
}
1628
1659
for ( let i = flast ; i >= 0 ; i -= 1 ) {
1629
1660
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
+ ) ) {
1631
1668
continue ;
1632
1669
}
1633
1670
let mgensScratch ;
@@ -1651,7 +1688,8 @@ function initSearch(rawSearchIndex) {
1651
1688
queryElems ,
1652
1689
whereClause ,
1653
1690
mgensScratch ,
1654
- solutionCb
1691
+ solutionCb ,
1692
+ unboxingDepth + 1
1655
1693
) ;
1656
1694
if ( passesUnification ) {
1657
1695
return true ;
@@ -1670,11 +1708,10 @@ function initSearch(rawSearchIndex) {
1670
1708
*
1671
1709
* @param {FunctionType } fnType
1672
1710
* @param {QueryElement } queryElem
1673
- * @param {[FunctionSearchType] } whereClause - Trait bounds for generic items.
1674
1711
* @param {Map<number,number>|null } mgensIn - Map functions generics to query generics.
1675
1712
* @returns {boolean }
1676
1713
*/
1677
- function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , whereClause , mgensIn ) {
1714
+ function unifyFunctionTypeIsMatchCandidate ( fnType , queryElem , mgensIn ) {
1678
1715
// type filters look like `trait:Read` or `enum:Result`
1679
1716
if ( ! typePassesFilter ( queryElem . typeFilter , fnType . ty ) ) {
1680
1717
return false ;
@@ -1775,9 +1812,16 @@ function initSearch(rawSearchIndex) {
1775
1812
* @param {[FunctionType] } whereClause - Trait bounds for generic items.
1776
1813
* @param {Map<number,number> } mgensIn - Map functions generics to query generics.
1777
1814
* Never modified.
1815
+ * @param {number } unboxingDepth
1778
1816
* @returns {false|{mgens: [Map<number,number>], simplifiedGenerics: [FunctionType]} }
1779
1817
*/
1780
- function unifyFunctionTypeCheckBindings ( fnType , queryElem , whereClause , mgensIn ) {
1818
+ function unifyFunctionTypeCheckBindings (
1819
+ fnType ,
1820
+ queryElem ,
1821
+ whereClause ,
1822
+ mgensIn ,
1823
+ unboxingDepth
1824
+ ) {
1781
1825
if ( fnType . bindings . size < queryElem . bindings . size ) {
1782
1826
return false ;
1783
1827
}
@@ -1804,7 +1848,8 @@ function initSearch(rawSearchIndex) {
1804
1848
// return `false` makes unifyFunctionTypes return the full set of
1805
1849
// possible solutions
1806
1850
return false ;
1807
- }
1851
+ } ,
1852
+ unboxingDepth
1808
1853
) ;
1809
1854
return newSolutions ;
1810
1855
} ) ;
@@ -1834,9 +1879,19 @@ function initSearch(rawSearchIndex) {
1834
1879
* @param {QueryElement } queryElem
1835
1880
* @param {[FunctionType] } whereClause - Trait bounds for generic items.
1836
1881
* @param {Map<number,number>|null } mgens - Map functions generics to query generics.
1882
+ * @param {number } unboxingDepth
1837
1883
* @returns {boolean }
1838
1884
*/
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
+ }
1840
1895
if ( fnType . id < 0 && queryElem . id >= 0 ) {
1841
1896
if ( ! whereClause ) {
1842
1897
return false ;
@@ -1858,14 +1913,21 @@ function initSearch(rawSearchIndex) {
1858
1913
whereClause [ ( - fnType . id ) - 1 ] ,
1859
1914
queryElem ,
1860
1915
whereClause ,
1861
- mgensTmp
1916
+ mgensTmp ,
1917
+ unboxingDepth
1862
1918
) ;
1863
1919
} else if ( fnType . generics . length > 0 || fnType . bindings . size > 0 ) {
1864
1920
const simplifiedGenerics = [
1865
1921
...fnType . generics ,
1866
1922
...Array . from ( fnType . bindings . values ( ) ) . flat ( ) ,
1867
1923
] ;
1868
- return checkIfInList ( simplifiedGenerics , queryElem , whereClause , mgens ) ;
1924
+ return checkIfInList (
1925
+ simplifiedGenerics ,
1926
+ queryElem ,
1927
+ whereClause ,
1928
+ mgens ,
1929
+ unboxingDepth
1930
+ ) ;
1869
1931
}
1870
1932
return false ;
1871
1933
}
@@ -1877,13 +1939,14 @@ function initSearch(rawSearchIndex) {
1877
1939
* @param {Array<FunctionType> } list
1878
1940
* @param {QueryElement } elem - The element from the parsed query.
1879
1941
* @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
1881
1944
*
1882
1945
* @return {boolean } - Returns true if found, false otherwise.
1883
1946
*/
1884
- function checkIfInList ( list , elem , whereClause , mgens ) {
1947
+ function checkIfInList ( list , elem , whereClause , mgens , unboxingDepth ) {
1885
1948
for ( const entry of list ) {
1886
- if ( checkType ( entry , elem , whereClause , mgens ) ) {
1949
+ if ( checkType ( entry , elem , whereClause , mgens , unboxingDepth ) ) {
1887
1950
return true ;
1888
1951
}
1889
1952
}
@@ -1897,14 +1960,23 @@ function initSearch(rawSearchIndex) {
1897
1960
* @param {Row } row
1898
1961
* @param {QueryElement } elem - The element from the parsed query.
1899
1962
* @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.
1901
1964
*
1902
1965
* @return {boolean } - Returns true if the type matches, false otherwise.
1903
1966
*/
1904
- function checkType ( row , elem , whereClause , mgens ) {
1967
+ function checkType ( row , elem , whereClause , mgens , unboxingDepth ) {
1968
+ if ( unboxingDepth >= UNBOXING_LIMIT ) {
1969
+ return false ;
1970
+ }
1905
1971
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
+ ) ;
1908
1980
}
1909
1981
if ( row . id > 0 && elem . id > 0 && elem . pathWithoutLast . length === 0 &&
1910
1982
typePassesFilter ( elem . typeFilter , row . ty ) && elem . generics . length === 0 &&
@@ -1916,11 +1988,12 @@ function initSearch(rawSearchIndex) {
1916
1988
row . generics ,
1917
1989
elem ,
1918
1990
whereClause ,
1919
- mgens
1991
+ mgens ,
1992
+ unboxingDepth
1920
1993
) ;
1921
1994
}
1922
1995
}
1923
- return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens ) ;
1996
+ return unifyFunctionTypes ( [ row ] , [ elem ] , whereClause , mgens , null , unboxingDepth ) ;
1924
1997
}
1925
1998
1926
1999
/**
@@ -2135,9 +2208,9 @@ function initSearch(rawSearchIndex) {
2135
2208
) ;
2136
2209
if ( tfpDist !== null ) {
2137
2210
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 ) ;
2139
2212
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 ) ;
2141
2214
if ( in_args ) {
2142
2215
results_in_args . max_dist = Math . max ( results_in_args . max_dist || 0 , tfpDist ) ;
2143
2216
const maxDist = results_in_args . size < MAX_RESULTS ?
@@ -2223,9 +2296,12 @@ function initSearch(rawSearchIndex) {
2223
2296
row . type . output ,
2224
2297
parsedQuery . returned ,
2225
2298
row . type . where_clause ,
2226
- mgens
2299
+ mgens ,
2300
+ null ,
2301
+ 0 // unboxing depth
2227
2302
) ;
2228
- }
2303
+ } ,
2304
+ 0 // unboxing depth
2229
2305
) ) {
2230
2306
return ;
2231
2307
}
0 commit comments