1
Fork 0

rustdoc-search: add support for associated types

This commit is contained in:
Michael Howell 2023-09-22 17:27:06 -07:00
parent 9a66e4471f
commit 63c50712f4
21 changed files with 1390 additions and 124 deletions

View 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': [],
},
];

View 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;
}

View 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': [],
},
];

View 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
View 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
View 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 {} }

View file

@ -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': [],
},
];

View 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' },
],
},
];

View file

@ -0,0 +1,4 @@
pub trait MyTrait {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}