rustdoc-search: add support for associated types
This commit is contained in:
parent
9a66e4471f
commit
63c50712f4
21 changed files with 1390 additions and 124 deletions
163
tests/rustdoc-js/assoc-type-backtrack.js
Normal file
163
tests/rustdoc-js/assoc-type-backtrack.js
Normal file
|
@ -0,0 +1,163 @@
|
|||
// 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' },
|
||||
],
|
||||
},
|
||||
// The first two define the base case.
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture<t>> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' },
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture<t>>, myintofuture<fut=myfuture<t>> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
// Unboxings of the one-argument case.
|
||||
{
|
||||
'query': 'myfuture<t> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' },
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<myfuture<t>> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' },
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
// Invalid unboxing of the one-argument case.
|
||||
// If you unbox one of the myfutures, you need to unbox both of them.
|
||||
{
|
||||
'query': 'myintofuture<fut=t> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
// Unboxings of the two-argument case.
|
||||
{
|
||||
'query': 'myintofuture<fut=t>, myintofuture<fut=t> -> t',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture>, myintofuture<fut=myfuture> -> myfuture',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<myfuture>, myintofuture<myfuture> -> myfuture',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'myfuture<t>, myfuture<t> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' },
|
||||
],
|
||||
},
|
||||
// Invalid unboxings of the two-argument case.
|
||||
// If you unbox one of the myfutures, you need to unbox all of them.
|
||||
{
|
||||
'query': 'myintofuture<fut=t>, myintofuture<fut=myfuture<t>> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture<t>>, myintofuture<fut=t> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture<t>>, myintofuture<fut=myfuture<t>> -> t',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
// different generics don't match up either
|
||||
{
|
||||
'query': 'myintofuture<fut=myfuture<u>>, myintofuture<fut=myfuture<t>> -> myfuture<t>',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
{
|
||||
'query': 'myintofuture<output=t> -> myfuture<tt>',
|
||||
'correction': null,
|
||||
'others': [],
|
||||
},
|
||||
];
|
38
tests/rustdoc-js/assoc-type-backtrack.rs
Normal file
38
tests/rustdoc-js/assoc-type-backtrack.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
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 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MyFuture {
|
||||
type Output;
|
||||
}
|
||||
|
||||
pub trait MyIntoFuture {
|
||||
type Output;
|
||||
type Fut: MyFuture<Output=Self::Output>;
|
||||
fn into_future(self) -> Self::Fut;
|
||||
fn into_future_2(self, other: Self) -> Self::Fut;
|
||||
}
|
45
tests/rustdoc-js/assoc-type.js
Normal file
45
tests/rustdoc-js/assoc-type.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
// exact-check
|
||||
|
||||
const EXPECTED = [
|
||||
// if I just use generics, then the generics version
|
||||
// and the type binding version both show up
|
||||
{
|
||||
'query': 'iterator<something> -> u32',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type', 'name': 'my_fn' },
|
||||
{ 'path': 'assoc_type::my', 'name': 'other_fn' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'iterator<something>',
|
||||
'correction': null,
|
||||
'in_args': [
|
||||
{ 'path': 'assoc_type', 'name': 'my_fn' },
|
||||
{ 'path': 'assoc_type::my', 'name': 'other_fn' },
|
||||
],
|
||||
},
|
||||
// if I write an explicit binding, only it shows up
|
||||
{
|
||||
'query': 'iterator<item=something> -> u32',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type', 'name': 'my_fn' },
|
||||
],
|
||||
},
|
||||
// case insensitivity
|
||||
{
|
||||
'query': 'iterator<ItEm=sOmEtHiNg> -> u32',
|
||||
'correction': null,
|
||||
'others': [
|
||||
{ 'path': 'assoc_type', 'name': 'my_fn' },
|
||||
],
|
||||
},
|
||||
// wrong binding name, no result
|
||||
{
|
||||
'query': 'iterator<something=something> -> u32',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [],
|
||||
},
|
||||
];
|
12
tests/rustdoc-js/assoc-type.rs
Normal file
12
tests/rustdoc-js/assoc-type.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
pub fn my_fn<X: Iterator<Item = Something>>(_x: X) -> u32 {
|
||||
3
|
||||
}
|
||||
|
||||
pub struct Something;
|
||||
|
||||
pub mod my {
|
||||
pub trait Iterator<T> {}
|
||||
pub fn other_fn<X: Iterator<crate::Something>>(_: X) -> u32 {
|
||||
3
|
||||
}
|
||||
}
|
57
tests/rustdoc-js/gat.js
Normal file
57
tests/rustdoc-js/gat.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
// exact-check
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'query': 'foo<assoc<u8>=u8> -> u32',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [
|
||||
{ 'path': 'gat', 'name': 'sample' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'foo<assoc<u8>=u8> -> !',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [
|
||||
{ 'path': 'gat', 'name': 'synergy' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'foo<assoc<u8>=u8>',
|
||||
'correction': null,
|
||||
'in_args': [
|
||||
{ 'path': 'gat', 'name': 'sample' },
|
||||
{ 'path': 'gat', 'name': 'synergy' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'foo<assoc<u8>=u32>',
|
||||
'correction': null,
|
||||
'in_args': [
|
||||
{ 'path': 'gat', 'name': 'consider' },
|
||||
],
|
||||
},
|
||||
{
|
||||
// This one is arguably a bug, because the way rustdoc
|
||||
// stores GATs in the search index is sloppy, but it's
|
||||
// precise enough to match most of the samples in the
|
||||
// GAT initiative repo
|
||||
'query': 'foo<assoc<u32>=u8>',
|
||||
'correction': null,
|
||||
'in_args': [
|
||||
{ 'path': 'gat', 'name': 'consider' },
|
||||
],
|
||||
},
|
||||
{
|
||||
// This one is arguably a bug, because the way rustdoc
|
||||
// stores GATs in the search index is sloppy, but it's
|
||||
// precise enough to match most of the samples in the
|
||||
// GAT initiative repo
|
||||
'query': 'foo<assoc<T>=T>',
|
||||
'correction': null,
|
||||
'in_args': [
|
||||
{ 'path': 'gat', 'name': 'integrate' },
|
||||
],
|
||||
},
|
||||
];
|
8
tests/rustdoc-js/gat.rs
Normal file
8
tests/rustdoc-js/gat.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
pub trait Foo {
|
||||
type Assoc<T>;
|
||||
}
|
||||
|
||||
pub fn sample<X: Foo<Assoc<u8> = u8>>(_: X) -> u32 { loop {} }
|
||||
pub fn synergy(_: impl Foo<Assoc<u8> = u8>) -> ! { loop {} }
|
||||
pub fn consider(_: impl Foo<Assoc<u8> = u32>) -> bool { loop {} }
|
||||
pub fn integrate<T>(_: impl Foo<Assoc<T> = T>) -> T { loop {} }
|
|
@ -43,4 +43,14 @@ const EXPECTED = [
|
|||
{ 'path': 'never_search', 'name': 'box_uninteresting' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'box<item=!>',
|
||||
'in_args': [],
|
||||
'returned': [],
|
||||
},
|
||||
{
|
||||
'query': 'box<item=never>',
|
||||
'in_args': [],
|
||||
'returned': [],
|
||||
},
|
||||
];
|
||||
|
|
12
tests/rustdoc-js/trait-methods.js
Normal file
12
tests/rustdoc-js/trait-methods.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// exact-check
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'query': 'mytrait<t> -> option<t>',
|
||||
'correction': null,
|
||||
'in_args': [],
|
||||
'others': [
|
||||
{ 'path': 'trait_methods::MyTrait', 'name': 'next' },
|
||||
],
|
||||
},
|
||||
];
|
4
tests/rustdoc-js/trait-methods.rs
Normal file
4
tests/rustdoc-js/trait-methods.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub trait MyTrait {
|
||||
type Item;
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue