diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 498b688ef995..ab0d663e26d7 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1545,11 +1545,12 @@ function initSearch(rawSearchIndex) { for (j = i; j !== fl; ++j) { const fnType = fnTypes[j]; if (unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens)) { + const mgensScratch = new Map(mgens); const simplifiedGenerics = unifyFunctionTypeCheckBindings( fnType, queryElem, whereClause, - mgens + mgensScratch ); if (simplifiedGenerics) { if (!fnTypesScratch) { @@ -1559,7 +1560,7 @@ function initSearch(rawSearchIndex) { simplifiedGenerics, queryElem.generics, whereClause, - mgens, + mgensScratch, mgensScratch => { matchCandidates.push({ fnTypesScratch, @@ -1635,7 +1636,7 @@ function initSearch(rawSearchIndex) { * * @param {FunctionType} fnType * @param {QueryElement} queryElem - * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {[FunctionSearchType]} whereClause - Trait bounds for generic items. * @param {Map|null} mgensIn - Map functions generics to query generics. * @returns {boolean} */ @@ -1725,10 +1726,11 @@ function initSearch(rawSearchIndex) { * @param {FunctionType} fnType * @param {QueryElement} queryElem * @param {[FunctionType]} whereClause - Trait bounds for generic items. - * @param {Map|null} mgensIn - Map functions generics to query generics. + * @param {Map|null} mgensInout - Map functions generics to query generics. + * Written on success. * @returns {boolean|FunctionType[]} */ - function unifyFunctionTypeCheckBindings(fnType, queryElem, whereClause, mgensIn) { + function unifyFunctionTypeCheckBindings(fnType, queryElem, whereClause, mgensInout) { // Simplify generics now let simplifiedGenerics = fnType.generics; if (!simplifiedGenerics) { @@ -1738,17 +1740,24 @@ function initSearch(rawSearchIndex) { return false; } if (fnType.bindings.size > 0) { + const mgensResults = new Map(mgensInout); for (const [name, constraints] of queryElem.bindings.entries()) { if (!fnType.bindings.has(name)) { return false; } // Since both items must have exactly one entry per name, - // we don't need to backtrack here. + // we don't need to backtrack here, but do need to write mgens. if (!unifyFunctionTypes( fnType.bindings.get(name), constraints, whereClause, - mgensIn + mgensResults, + mgens => { + for (const [fid, qid] of mgens.entries()) { + mgensResults.set(fid, qid); + } + return true; + } )) { return false; } @@ -1766,6 +1775,11 @@ function initSearch(rawSearchIndex) { } else { simplifiedGenerics = binds; } + if (mgensInout) { + for (const [fid, qid] of mgensResults.entries()) { + mgensInout.set(fid, qid); + } + } } return simplifiedGenerics; } diff --git a/tests/rustdoc-js/assoc-type-backtrack.js b/tests/rustdoc-js/assoc-type-backtrack.js new file mode 100644 index 000000000000..6560cac7ca45 --- /dev/null +++ b/tests/rustdoc-js/assoc-type-backtrack.js @@ -0,0 +1,66 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' }, + ], + }, +]; diff --git a/tests/rustdoc-js/assoc-type-backtrack.rs b/tests/rustdoc-js/assoc-type-backtrack.rs new file mode 100644 index 000000000000..8e167ad8e7b7 --- /dev/null +++ b/tests/rustdoc-js/assoc-type-backtrack.rs @@ -0,0 +1,27 @@ +pub trait MyTrait2 { + type Output; +} + +pub trait MyTrait { + type Item; + fn next(&mut self) -> Option; + fn fold(self, init: B, f: F) -> B where + Self: Sized, + F: MyTrait2<(B, Self::Item), Output=B>; +} + +pub struct Cloned(I); + +impl<'a, T, I> MyTrait for Cloned where + T: 'a + Clone, + I: MyTrait +{ + type Item = T; + fn next(&mut self) -> Option { loop {} } + fn fold(self, init: B, f: F) -> B where + Self: Sized, + F: MyTrait2<(B, Self::Item), Output=B> + { + loop {} + } +}