-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better pattern argument naming in rustdoc #97048
Comments
In such case, I think generating something like: fn func(_: Foo) {} would work out nicely enough. |
Except that someone might think that because it's |
I'm not sure that printing |
Agree, printing |
It's not great either... Any opinion on this @rust-lang/rustdoc? |
Can we pass through exactly what was written in the source code by the author? |
I suppose so, but once again: would this destructuring information be useful for the doc reader? |
Yes. For instance, if a destructuring only cares about a single field of a big struct, it's useful for the caller to know that only that one field matters. Also, passing through the original improves predictability. People's general mental model of what shows up in rustdoc is "the function signature as written, plus some hyperlinks and formatting." It's confusing to deviate from that. |
This is a good point. My main worry was the complexification of the doc but I guess it's secondary. |
But that's a implementation detail not a promise. The field might be private and this would be even more confusing for the reader. |
This is true - but I think it's more confusing (for both the author and the reader) for the documented function signature to be different from what's written in the code. If the author wants to make sure users can't see the destructuring, they can put it inside the function. If the author does want users to see the destructuring, they can put it in the function signature. This approach gives both predictability and flexibility for the doc author. |
But the problem about private fields remains though. And it's quite a big one. |
If the function signature includes a destructuring that names a private field, we should go ahead and list that name, with a doc lint saying "this function signature exposes the name of a private field." |
That seems like way too much useless information. Why would this be useful for the reader? For me it looks like explanations about what they're reading. It seems more confusing than useful. I didn't expect this issue to be so complicated. 😄 |
It isn't invalid. People should not rely on this. Doing this would change the semantics of this de-structuring from just being a sugar for the dev to something that is important and that API dev must take into account. That would be a major change. And that doesn't even take into account the useless information for the reader:
|
That's a decision for the doc author to make, not rustdoc. Rustdoc's role is to provide a powerful, predictable tool. The doc author's role is to structure their code so that it provides useful information when rendered by rustdoc. Here's an analogy: the names of function parameters are not used by the caller. But we include them in rustdoc output because they are useful in giving a hint about what that parameter will do. Since doc authors know the parameter names become part of the public documentation, they don't name parameters |
I understand your point, but don't agree with all of it (and also don't completely agree with your analogy as you're mixing two different things). As soon as a destructured parameter is using a private field, then it doesn't provide useful information to the reader. So unless For me rustdoc has two different kind of usage:
|
This could be even a security/logic issue. Example, a dev write this: pub struct Struct {
pub bar: u8,
pub security_bit: u8
}
pub fn func(Struct { bar, .. }: Struct) {} But than change it to: pub struct Struct {
pub bar: u8,
pub security_bit: u8
}
pub fn func(Struct { bar, security_bit }: Struct) {} Someone looking at the first version realize that |
Regarding the private fields, I raised an issue a year ago showing that public functions can return 'private' types. rustdoc includes the type name in that return position, just it doesn't include any link to documentation for that type. Whether a function argument destructuring contains private fields or not I think is irrelevant. I also don't know what kind of security problems it would cause since the source code is all publicly available anyhow. The main reason I raised this issue was that I felt that without a proper name, function arguments can be very difficult to understand. |
I disagree showing private would not be helpful and would just add more distraction.
Imaging that
I think we all agree on this and we're trying to find the best solution for it. As my final words on this issue I agree with @GuillaumeGomez: "So unless document-private is used, I think it shouldn't be displayed." and I don't know what should be displayed in the non document-private case. |
There is a theme that comes up frequently for rustdoc: we want to produce the most useful docs for the reader. Are we doing that in spite of the doc author, or in collaboration with the doc author? In other words, should we expect that the doc author is writing their public API with an eye towards documentation? I think rustdoc has to be in collaboration with the doc author. There are some ways a doc author can write code such that we can't make good docs out of them, and the solution is to fix the code, not try to work around it in rustdoc.
Agreed. The names of function parameters are an important part of the documentation, and they're chosen by the doc author. When the doc author uses a destructuring in a public function signature, they haven't given us a meaningful name we can show in the docs. There few options:
(4) is the only approach that can possibly yield good docs. So we should encourage doc authors to do (4). In the cases where they don't, rustdoc should do whatever is simplest (implemenation-wise, or conceptually simplest). |
I think I agree with this conclusion. It's just a shame this feature would be unrecommended in lib code beyond the use of something like |
Strong agree with this btw |
I'd choose between these two options for rendering
Both options are defensible. The first one is less noisy, and is probably fine given how often the type really is enough and you don't actually need a name. The second is defensible on "show the source code as written" grounds. |
I don't think private field naming being leaked is a problem, it may happen to also be the name of a private field, but it is just a variable binding which can be seen by renaming it...
Edit: I would personally rather read pattern matches than e.g. |
I slightly prefer truncation because the pattern destructuring IME is more for the internal code's benefit than for the external API benefit |
There's three contexts in which a function signature is displayed in docs:
There's also, as mentioned briefly above, two cases for patterns in signatures:
I feel like there could be a design where the pattern is surfaced in some of these cases but not all. Additionally, it's been pointed out you can influence the doc's autonaming using pub fn function(_name @ Arg { field, .. }: Arg) {} which renders to: pub fn function(_name: Arg) {} so the code's author can already avoid having the docs be confusing due to the autogenerated name, at the slight cost of some extra noise in the pattern. |
There is also some minor precedent in not showing pattern details in that Tangentially, #35203 may contain interesting context to this discussion. |
I noticed with function pattern arguments that rustdoc makes some interesting choices regarding argument names.
For instance:
gets rustdoc'd into
(see
https://docs.rs/atuin-server/0.9.1/atuin_server/handlers/history/fn.calendar.html for a real life version)
It's hard to say what rustdoc should do in the general case, but there are some simple cases that could be improved.
For the single capture pattern, the argument could inherit the name. Eg, in the example above, it could be rendered as
bar: Foo
.However, this single capture rule should maybe not apply if in a case like
Since
bar
might be a small subset of what the type is representing, and might be misleading (or implementation detail).In the general case, the argument name could be a snake case version of the type name, if no conflicts. This is the best heuristic I can come up with for a sensible name
The text was updated successfully, but these errors were encountered: