Skip to content

Commit

Permalink
rustdoc: fix generics tracking bug in type binding
Browse files Browse the repository at this point in the history
  • Loading branch information
notriddle committed Oct 4, 2023
1 parent 20aed8b commit b0a34a8
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 7 deletions.
28 changes: 21 additions & 7 deletions src/librustdoc/html/static/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -1559,7 +1560,7 @@ function initSearch(rawSearchIndex) {
simplifiedGenerics,
queryElem.generics,
whereClause,
mgens,
mgensScratch,
mgensScratch => {
matchCandidates.push({
fnTypesScratch,
Expand Down Expand Up @@ -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<number,number>|null} mgensIn - Map functions generics to query generics.
* @returns {boolean}
*/
Expand Down Expand Up @@ -1725,10 +1726,11 @@ function initSearch(rawSearchIndex) {
* @param {FunctionType} fnType
* @param {QueryElement} queryElem
* @param {[FunctionType]} whereClause - Trait bounds for generic items.
* @param {Map<number,number>|null} mgensIn - Map functions generics to query generics.
* @param {Map<number,number>|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) {
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
66 changes: 66 additions & 0 deletions tests/rustdoc-js/assoc-type-backtrack.js
Original file line number Diff line number Diff line change
@@ -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<U>, mytrait2 -> T',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' },
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
],
},
{
'query': 'mytrait<Item=U>, mytrait2 -> T',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' },
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
],
},
{
'query': 'mytrait<T>, mytrait2 -> T',
'correction': null,
'others': [],
},
{
'query': 'mytrait<Item=T>, mytrait2 -> T',
'correction': null,
'others': [],
},
{
'query': 'mytrait<T> -> Option<T>',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' },
],
},
{
'query': 'mytrait<Item=T> -> Option<T>',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' },
],
},
{
'query': 'mytrait<U> -> Option<T>',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' },
],
},
{
'query': 'mytrait<Item=U> -> Option<T>',
'correction': null,
'others': [
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' },
],
},
];
27 changes: 27 additions & 0 deletions tests/rustdoc-js/assoc-type-backtrack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
pub trait MyTrait2<X> {
type Output;
}

pub trait MyTrait {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn fold<B, F>(self, init: B, f: F) -> B where
Self: Sized,
F: MyTrait2<(B, Self::Item), Output=B>;
}

pub struct Cloned<I>(I);

impl<'a, T, I> MyTrait for Cloned<I> where
T: 'a + Clone,
I: MyTrait<Item = &'a T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> { loop {} }
fn fold<B, F>(self, init: B, f: F) -> B where
Self: Sized,
F: MyTrait2<(B, Self::Item), Output=B>
{
loop {}
}
}

0 comments on commit b0a34a8

Please sign in to comment.