diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 4822690fd04b6..0bb56cd971013 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1755,17 +1755,26 @@ function initSearch(rawSearchIndex) {
if (mgens && mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) {
return false;
}
+ // Where clauses can represent cyclical data.
+ // `null` prevents it from trying to unbox in an infinite loop
+ const mgensTmp = new Map(mgens);
+ mgensTmp.set(fnType.id, null);
// This is only a potential unbox if the search query appears in the where clause
// for example, searching `Read -> usize` should find
// `fn read_all(R) -> Result`
// generic `R` is considered "unboxed"
- return checkIfInList(whereClause[(-fnType.id) - 1], queryElem, whereClause);
+ return checkIfInList(
+ whereClause[(-fnType.id) - 1],
+ queryElem,
+ whereClause,
+ mgensTmp
+ );
} else if (fnType.generics.length > 0 || fnType.bindings.size > 0) {
const simplifiedGenerics = [
...fnType.generics,
...Array.from(fnType.bindings.values()).flat(),
];
- return checkIfInList(simplifiedGenerics, queryElem, whereClause);
+ return checkIfInList(simplifiedGenerics, queryElem, whereClause, mgens);
}
return false;
}
@@ -1777,12 +1786,13 @@ function initSearch(rawSearchIndex) {
* @param {Array} list
* @param {QueryElement} elem - The element from the parsed query.
* @param {[FunctionType]} whereClause - Trait bounds for generic items.
+ * @param {Map|null} mgens - Map functions generics to query generics.
*
* @return {boolean} - Returns true if found, false otherwise.
*/
- function checkIfInList(list, elem, whereClause) {
+ function checkIfInList(list, elem, whereClause, mgens) {
for (const entry of list) {
- if (checkType(entry, elem, whereClause)) {
+ if (checkType(entry, elem, whereClause, mgens)) {
return true;
}
}
@@ -1796,23 +1806,29 @@ function initSearch(rawSearchIndex) {
* @param {Row} row
* @param {QueryElement} elem - The element from the parsed query.
* @param {[FunctionType]} whereClause - Trait bounds for generic items.
+ * @param {Map|null} mgens - Map functions generics to query generics.
*
* @return {boolean} - Returns true if the type matches, false otherwise.
*/
- function checkType(row, elem, whereClause) {
+ function checkType(row, elem, whereClause, mgens) {
if (row.bindings.size === 0 && elem.bindings.size === 0) {
if (elem.id < 0) {
- return row.id < 0 || checkIfInList(row.generics, elem, whereClause);
+ return row.id < 0 || checkIfInList(row.generics, elem, whereClause, mgens);
}
if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 &&
typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 &&
// special case
elem.id !== typeNameIdOfArrayOrSlice
) {
- return row.id === elem.id || checkIfInList(row.generics, elem, whereClause);
+ return row.id === elem.id || checkIfInList(
+ row.generics,
+ elem,
+ whereClause,
+ mgens
+ );
}
}
- return unifyFunctionTypes([row], [elem], whereClause);
+ return unifyFunctionTypes([row], [elem], whereClause, mgens);
}
function checkPath(contains, ty, maxEditDistance) {
diff --git a/tests/rustdoc-js/assoc-type-loop.js b/tests/rustdoc-js/assoc-type-loop.js
new file mode 100644
index 0000000000000..f0192371ab41a
--- /dev/null
+++ b/tests/rustdoc-js/assoc-type-loop.js
@@ -0,0 +1,9 @@
+// Crash reduction of
+// https://github.com/rust-lang/rust/issues/118242
+
+const EXPECTED = [
+ {
+ 'query': 't',
+ 'correction': null,
+ },
+];
diff --git a/tests/rustdoc-js/assoc-type-loop.rs b/tests/rustdoc-js/assoc-type-loop.rs
new file mode 100644
index 0000000000000..f123c83f50fdf
--- /dev/null
+++ b/tests/rustdoc-js/assoc-type-loop.rs
@@ -0,0 +1,35 @@
+#![crate_name="foo"]
+
+// reduced from sqlx 0.7.3
+use std::future::Future;
+use std::pin::Pin;
+use std::ops::{Deref, DerefMut};
+pub enum Error {}
+pub trait Acquire<'c> {
+ type Database: Database;
+ type Connection: Deref::Connection> + DerefMut + Send;
+}
+pub trait Database {
+ type Connection: Connection;
+}
+pub trait Connection {
+ type Database: Database;
+ type Options: ConnectionOptions;
+ fn begin(
+ &mut self
+ ) -> Pin, Error>> + Send + '_>>
+ where
+ Self: Sized;
+}
+pub trait ConnectionOptions {
+ type Connection: Connection;
+}
+pub struct Transaction<'c, DB: Database> {
+ _db: &'c DB,
+}
+impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB>
+ where ::Connection: Send
+{
+ type Database = DB;
+ type Connection = &'t mut ::Connection;
+}