@@ -1318,7 +1318,7 @@ function initSearch(rawSearchIndex) {
13181318 * then this function will try with a different solution, or bail with false if it
13191319 * runs out of candidates.
13201320 *
1321- * @param {Array<FunctionType>} fnTypes - The objects to check.
1321+ * @param {Array<FunctionType>} fnTypesIn - The objects to check.
13221322 * @param {Array<QueryElement>} queryElems - The elements from the parsed query.
13231323 * @param {[FunctionType]} whereClause - Trait bounds for generic items.
13241324 * @param {Map<number,number>|null} mgensIn
@@ -1340,6 +1340,79 @@ function initSearch(rawSearchIndex) {
13401340 }
13411341 const ql = queryElems.length;
13421342 let fl = fnTypesIn.length;
1343+
1344+ // Fast path
1345+ if (queryElems.length === 1 && queryElems[0].generics.length === 0) {
1346+ const queryElem = queryElems[0];
1347+ for (const fnType of fnTypesIn) {
1348+ if (!unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens)) {
1349+ continue;
1350+ }
1351+ if (fnType.id < 0 && queryElem.id < 0) {
1352+ if (mgens === null) {
1353+ mgens = new Map();
1354+ }
1355+ const alreadyAssigned = mgens.has(fnType.id);
1356+ if (alreadyAssigned) {
1357+ if (mgens.get(fnType.id) !== queryElem.id) {
1358+ continue;
1359+ }
1360+ } else {
1361+ mgens.set(fnType.id, queryElem.id);
1362+ }
1363+ if (!solutionCb || solutionCb(mgens)) {
1364+ return true;
1365+ }
1366+ if (!alreadyAssigned) {
1367+ mgens.delete(fnType.id);
1368+ }
1369+ } else if (!solutionCb || solutionCb(mgens)) {
1370+ // unifyFunctionTypeIsMatchCandidate already checks that ids match
1371+ return true;
1372+ }
1373+ }
1374+ for (const fnType of fnTypesIn) {
1375+ if (!unifyFunctionTypeIsUnboxCandidate(fnType, queryElem, whereClause, mgens)) {
1376+ continue;
1377+ }
1378+ if (fnType.id < 0) {
1379+ if (mgens === null) {
1380+ mgens = new Map();
1381+ }
1382+ const alreadyAssigned = mgens.has(fnType.id);
1383+ if (alreadyAssigned) {
1384+ if (mgens.get(fnType.id) !== 0) {
1385+ continue;
1386+ }
1387+ } else {
1388+ mgens.set(fnType.id, 0);
1389+ }
1390+ if (unifyFunctionTypes(
1391+ whereClause[(-fnType.id) - 1],
1392+ queryElems,
1393+ whereClause,
1394+ mgens,
1395+ solutionCb
1396+ )) {
1397+ return true;
1398+ }
1399+ if (!alreadyAssigned) {
1400+ mgens.delete(fnType.id);
1401+ }
1402+ } else if (unifyFunctionTypes(
1403+ fnType.generics,
1404+ queryElems,
1405+ whereClause,
1406+ mgens,
1407+ solutionCb
1408+ )) {
1409+ return true;
1410+ }
1411+ }
1412+ return false;
1413+ }
1414+
1415+ // Slow path
13431416 /**
13441417 * @type Array<FunctionType>
13451418 */
@@ -1405,7 +1478,8 @@ function initSearch(rawSearchIndex) {
14051478 if (fnType.id < 0) {
14061479 if (mgens === null) {
14071480 mgens = new Map();
1408- } else if (mgens.has(fnType.id) && mgens.get(fnType.id) !== queryElem.id) {
1481+ } else if (mgens.has(fnType.id) &&
1482+ mgens.get(fnType.id) !== queryElem.id) {
14091483 continue;
14101484 }
14111485 mgens.set(fnType.id, queryElem.id);
0 commit comments