In rust-xcb I have the following code:
/// a key was pressed/released
pub type KeyPressEvent = base::Event<xcb_key_press_event_t>;
impl KeyPressEvent {
/// The keycode (a number representing a physical key on the keyboard) of the key
/// which was pressed.
pub fn detail(&self) -> Keycode { ... }
/// Time when the event was generated (in milliseconds).
pub fn time(&self) -> Timestamp { ... }
...
}
However as one can see here, the impl section is ignored.
Yes, they're currently ignored. I believe @alexcrichton was the one who made this change?
This was never really "added" or "changed", it's just a bug in the implementation.
@srinivasreddy No I'm not, but I'd be happy to see this fixed
@rtbo Thanks for confirmation. I am on it.
What is the expectation here?
To only show direct impls on the typedef (impl KeyPressEvent ...
) or to show all impls on the type the typedef is referencing? (impl base::Event<xcb_key_press_event_t> ...
)
related #19381
@mitaa my expectation would be to have on the rustdoc page of the type
alias the methods documentation from the same alias.
I'd say methods from the original type that apply should be shown here, just like methods from Deref
s would.
Wonder whether it's still considered a known/ignored rustdoc bug? It's a bit of a PITA for crates that defined most types as specialisations, which is a quite common part in FFI-heavy code (this and the fact that typedefs are eagerly expanded everywhere even when it doesn't make much sense).
+1 on this, https://docs.rs/xi-rope/0.2.0/xi_rope/rope/type.Rope.html is missing all the impl Rope methods, which is where so much of the good stuff is.
I am looking into this, as it makes rust-xcb
quite difficult to use. It's my first time poking around in the rustdoc code, so it might take me a little while.
My initial prototype renders this code:
pub trait Trait1 {
/// From Trait1
fn trait_func1();
}
pub trait Trait2 {
/// From Trait2
fn trait_func2();
}
/// This is a MyStruct.
pub struct MyStruct;
impl MyStruct {
/// do_stuff() with MyStruct
pub fn do_stuff(&self) {}
}
impl Trait1 for MyStruct {
fn trait_func1() {}
}
/// This is a MyAlias
pub type MyAlias = MyStruct;
impl MyAlias {
/// do_more_stuff() with MyAlias
pub fn do_more_stuff(&self) {}
}
impl Trait2 for MyAlias {
fn trait_func2() {}
}
... like this:
I haven't played around with Deref
to see how it interacts, but I'll do that next.
I'd missed that there was a PR (#25892) referenced from related issue #19381, which took a similar approach to the one I was preparing. That PR was closed as @alexcrichton pointed out:
I'm also not sure if we want to take this route just yet due to #14072. For example on the documentation page for
io::Result
the parameterE
is generic instead of being wired up toError
.
You can see this in the following example:
/// A generic struct.
pub struct GenericStruct<T> {
i: T
}
impl<T> GenericStruct<T> {
/// A method on TypedefStruct.
pub fn generic_impl_method(arg: T) {}
}
/// A typedef for GenericStruct, without any generics.
pub type TypedefStruct = GenericStruct<u8>;
impl TypedefStruct {
/// A method on TypedefStruct.
pub fn typedef_impl_method() {}
}
... which renders as:
In the impl
for GenericStruct
, it isn't obvious that the type variable T
is u8
.
I had a look at coming up with a solution for #14072, but it's very involved and I think it's beyond my abilities. I'll continue to take a look, but I am not optimistic!
From the closed PR #25892:
I suppose it's also somewhat unclear to me what the motivation for this is because finding the documentation of the typedef itself should just be following a link.
It is worth pointing out, that in the case of rust-xcb
, it has impl
blocks on type aliases, which aren't visible anywhere in the docs due to this issue. It's especially hard to discover the API, as the impl
blocks are automatically generated bindings.
Would it be an improvement if the page for TypedefStruct
would show only the default impl
and trait impl
s made directly on TypedefStruct
, but nothing for GenericStruct
? The user can still click on the GenericStruct
to get to the rest of the documentation, as they do today. (This solution isn't ideal, but it avoids making #14072 worse).
This is also badly needed in nalgebra, which suffers both from otherwise-invisible impl
blocks and from its type aliases ultimately resolving to complicated generic types which have a very large number of methods, most of which are not relevant to any particular alias the user might be coming from. In this case, displaying the otherwise-invisible impl
blocks would be an improvement, though it wouldn't be a complete solution.
This is also badly needed in nalgebra, which suffers both from otherwise-invisible
impl
blocks and from its type aliases ultimately resolving to complicated generic types which have a very large number of methods, most of which are not relevant to any particular alias the user might be coming from.
Ah, I hadn't even considered the need to recursively follow type aliases, which would be necessary for nalgebra:
type Matrix2<N> = MatrixN<N, U2>;
type MatrixN<N, D> = MatrixNM<N, D, D>;
type MatrixNM<N, R, C> = Matrix<N, R, C, MatrixArray<N, R, C>>;
pub struct Matrix<N: Scalar, R: Dim, C: Dim, S> { .. }
// Ideally this would be visible in the documentation for Matrix2<N>,
// with the correct types substituted throughout the impl:
impl<N, R: Dim, C: Dim, S> Matrix<N, R, C, S>
where N: Scalar + ClosedNeg,
S: StorageMut<N, R, C> { .. }
In this case, displaying the otherwise-invisible impl blocks would be an improvement, though it wouldn't be a complete solution.
I've created a pull request (#42027) for this simple improvement.
@mjkillough Just to add, in my case it looks like this:
trait ID {}
struct Object<T: ID> {}
impl<T: ID> Object<T: ID> { /* shared methods */ }
struct FileID {}
impl ID for FileID {}
pub type File = Object<FileID>;
impl File { /* file-specific methods */ }
struct GroupID {}
impl ID for GroupID {}
pub type Group = Object<GroupID>;
impl Group { /* group-specific methods */ }
trait ContainerID : ID {}
impl ContainerID for FileID {}
impl ContainerID for GroupID {}
impl<T: ContainerID> Object<T> { /* container methods */ }
This way, help for File
would ideally display (1) base methods from Object, (2) methods from File, (3) shared Container methods. Currently, it displays none, of course...
(e.g. this example and this one, may also involve #14072 to some extent...)
What is the status of this issue? It has very unfortunate consequences on the rustsim family of crates (nalgebra, nphysics, etc.) which extensively use type definitions. Much of their generated documentation ends up basically useless because all methods on some type are actually implemented on a more generic version of it.
Are there any known workarounds? Mentoring instructions if someone wanted to work on this?
@fintelia Don鈥檛 think there鈥檚 any workarounds...
Most helpful comment
This is also badly needed in nalgebra, which suffers both from otherwise-invisible
impl
blocks and from its type aliases ultimately resolving to complicated generic types which have a very large number of methods, most of which are not relevant to any particular alias the user might be coming from. In this case, displaying the otherwise-invisibleimpl
blocks would be an improvement, though it wouldn't be a complete solution.