Skip to content

Commit 8ccc89b

Browse files
committedMar 5, 2021
Auto merge of #82777 - GuillaumeGomez:rollup-etcsupl, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - #76716 (Don't warn for `missing_doc_examples` when item is #[doc(hidden)]) - #82088 (Shorten html::render) - #82690 (Update rustdoc documentation) - #82752 (Add a regression test for issue-81712) - #82765 (Fix polymorphization ICE on associated types in trait decls using const generics in bounds) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents a0d66b5 + f74231f commit 8ccc89b

19 files changed

+2939
-2863
lines changed
 

‎compiler/rustc_middle/src/mir/query.rs

-12
Original file line numberDiff line numberDiff line change
@@ -438,18 +438,6 @@ impl<'tcx> TyCtxt<'tcx> {
438438
}
439439
}
440440

441-
#[inline]
442-
pub fn optimized_mir_or_const_arg_mir(
443-
self,
444-
def: ty::WithOptConstParam<DefId>,
445-
) -> &'tcx Body<'tcx> {
446-
if let Some((did, param_did)) = def.as_const_arg() {
447-
self.mir_for_ctfe_of_const_arg((did, param_did))
448-
} else {
449-
self.optimized_mir(def.did)
450-
}
451-
}
452-
453441
#[inline]
454442
pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
455443
if let Some((did, param_did)) = def.as_const_arg() {

‎compiler/rustc_middle/src/ty/instance.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl<'tcx> Instance<'tcx> {
499499
}
500500

501501
/// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
502-
/// identify parameters if they are determined to be unused in `instance.def`.
502+
/// identity parameters if they are determined to be unused in `instance.def`.
503503
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
504504
debug!("polymorphize: running polymorphization analysis");
505505
if !tcx.sess.opts.debugging_opts.polymorphize {

‎compiler/rustc_middle/src/ty/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2963,7 +2963,10 @@ impl<'tcx> TyCtxt<'tcx> {
29632963
| DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def),
29642964
// If the caller wants `mir_for_ctfe` of a function they should not be using
29652965
// `instance_mir`, so we'll assume const fn also wants the optimized version.
2966-
_ => self.optimized_mir_or_const_arg_mir(def),
2966+
_ => {
2967+
assert_eq!(def.const_param_did, None);
2968+
self.optimized_mir(def.did)
2969+
}
29672970
},
29682971
ty::InstanceDef::VtableShim(..)
29692972
| ty::InstanceDef::ReifyShim(..)

‎compiler/rustc_mir/src/monomorphize/polymorphize.rs

+64-40
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ pub fn provide(providers: &mut Providers) {
3030
/// Determine which generic parameters are used by the function/method/closure represented by
3131
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
3232
/// indicates all parameters are used).
33+
#[instrument(skip(tcx))]
3334
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
34-
debug!("unused_generic_params({:?})", def_id);
35-
3635
if !tcx.sess.opts.debugging_opts.polymorphize {
3736
// If polymorphization disabled, then all parameters are used.
3837
return FiniteBitSet::new_empty();
@@ -46,7 +45,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
4645
}
4746

4847
let generics = tcx.generics_of(def_id);
49-
debug!("unused_generic_params: generics={:?}", generics);
48+
debug!(?generics);
5049

5150
// Exit early when there are no parameters to be unused.
5251
if generics.count() == 0 {
@@ -57,11 +56,11 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
5756
let context = tcx.hir().body_const_context(def_id.expect_local());
5857
match context {
5958
Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
60-
debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
59+
debug!("no mir available");
6160
return FiniteBitSet::new_empty();
6261
}
6362
Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
64-
debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
63+
debug!("no ctfe mir available");
6564
return FiniteBitSet::new_empty();
6665
}
6766
_ => {}
@@ -72,9 +71,9 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
7271
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
7372
let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
7473
unused_parameters.set_range(0..generics_count);
75-
debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
74+
debug!(?unused_parameters, "(start)");
7675
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
77-
debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);
76+
debug!(?unused_parameters, "(after default)");
7877

7978
// Visit MIR and accumululate used generic parameters.
8079
let body = match context {
@@ -85,10 +84,10 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
8584
};
8685
let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
8786
vis.visit_body(body);
88-
debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
87+
debug!(?unused_parameters, "(after visitor)");
8988

9089
mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
91-
debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters);
90+
debug!(?unused_parameters, "(end)");
9291

9392
// Emit errors for debugging and testing if enabled.
9493
if !unused_parameters.is_empty() {
@@ -101,24 +100,55 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
101100
/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
102101
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
103102
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
103+
#[instrument(skip(tcx, def_id, generics, unused_parameters))]
104104
fn mark_used_by_default_parameters<'tcx>(
105105
tcx: TyCtxt<'tcx>,
106106
def_id: DefId,
107107
generics: &'tcx ty::Generics,
108108
unused_parameters: &mut FiniteBitSet<u32>,
109109
) {
110-
if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
111-
for param in &generics.params {
112-
debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param);
113-
unused_parameters.clear(param.index);
114-
}
115-
} else {
116-
for param in &generics.params {
117-
debug!("mark_used_by_default_parameters: (other) param={:?}", param);
118-
if let ty::GenericParamDefKind::Lifetime = param.kind {
110+
match tcx.def_kind(def_id) {
111+
DefKind::Closure | DefKind::Generator => {
112+
for param in &generics.params {
113+
debug!(?param, "(closure/gen)");
119114
unused_parameters.clear(param.index);
120115
}
121116
}
117+
DefKind::Mod
118+
| DefKind::Struct
119+
| DefKind::Union
120+
| DefKind::Enum
121+
| DefKind::Variant
122+
| DefKind::Trait
123+
| DefKind::TyAlias
124+
| DefKind::ForeignTy
125+
| DefKind::TraitAlias
126+
| DefKind::AssocTy
127+
| DefKind::TyParam
128+
| DefKind::Fn
129+
| DefKind::Const
130+
| DefKind::ConstParam
131+
| DefKind::Static
132+
| DefKind::Ctor(_, _)
133+
| DefKind::AssocFn
134+
| DefKind::AssocConst
135+
| DefKind::Macro(_)
136+
| DefKind::ExternCrate
137+
| DefKind::Use
138+
| DefKind::ForeignMod
139+
| DefKind::AnonConst
140+
| DefKind::OpaqueTy
141+
| DefKind::Field
142+
| DefKind::LifetimeParam
143+
| DefKind::GlobalAsm
144+
| DefKind::Impl => {
145+
for param in &generics.params {
146+
debug!(?param, "(other)");
147+
if let ty::GenericParamDefKind::Lifetime = param.kind {
148+
unused_parameters.clear(param.index);
149+
}
150+
}
151+
}
122152
}
123153

124154
if let Some(parent) = generics.parent {
@@ -128,23 +158,20 @@ fn mark_used_by_default_parameters<'tcx>(
128158

129159
/// Search the predicates on used generic parameters for any unused generic parameters, and mark
130160
/// those as used.
161+
#[instrument(skip(tcx, def_id))]
131162
fn mark_used_by_predicates<'tcx>(
132163
tcx: TyCtxt<'tcx>,
133164
def_id: DefId,
134165
unused_parameters: &mut FiniteBitSet<u32>,
135166
) {
136167
let def_id = tcx.closure_base_def_id(def_id);
137168
let predicates = tcx.explicit_predicates_of(def_id);
138-
debug!("mark_used_by_predicates: predicates_of={:?}", predicates);
139169

140170
let mut current_unused_parameters = FiniteBitSet::new_empty();
141171
// Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
142172
// bit set so that this is skipped if all parameters are already used.
143173
while current_unused_parameters != *unused_parameters {
144-
debug!(
145-
"mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
146-
current_unused_parameters, unused_parameters
147-
);
174+
debug!(?current_unused_parameters, ?unused_parameters);
148175
current_unused_parameters = *unused_parameters;
149176

150177
for (predicate, _) in predicates.predicates {
@@ -169,13 +196,13 @@ fn mark_used_by_predicates<'tcx>(
169196

170197
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
171198
/// parameter which was unused.
199+
#[instrument(skip(tcx, generics))]
172200
fn emit_unused_generic_params_error<'tcx>(
173201
tcx: TyCtxt<'tcx>,
174202
def_id: DefId,
175203
generics: &'tcx ty::Generics,
176204
unused_parameters: &FiniteBitSet<u32>,
177205
) {
178-
debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
179206
let base_def_id = tcx.closure_base_def_id(def_id);
180207
if !tcx
181208
.get_attrs(base_def_id)
@@ -185,7 +212,6 @@ fn emit_unused_generic_params_error<'tcx>(
185212
return;
186213
}
187214

188-
debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters);
189215
let fn_span = match tcx.opt_item_name(def_id) {
190216
Some(ident) => ident.span,
191217
_ => tcx.def_span(def_id),
@@ -197,7 +223,7 @@ fn emit_unused_generic_params_error<'tcx>(
197223
while let Some(generics) = next_generics {
198224
for param in &generics.params {
199225
if unused_parameters.contains(param.index).unwrap_or(false) {
200-
debug!("emit_unused_generic_params_error: param={:?}", param);
226+
debug!(?param);
201227
let def_span = tcx.def_span(param.def_id);
202228
err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
203229
}
@@ -219,33 +245,31 @@ struct MarkUsedGenericParams<'a, 'tcx> {
219245
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
220246
/// Invoke `unused_generic_params` on a body contained within the current item (e.g.
221247
/// a closure, generator or constant).
248+
#[instrument(skip(self, def_id, substs))]
222249
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
223250
let unused = self.tcx.unused_generic_params(def_id);
224-
debug!(
225-
"visit_child_body: unused_parameters={:?} unused={:?}",
226-
self.unused_parameters, unused
227-
);
251+
debug!(?self.unused_parameters, ?unused);
228252
for (i, arg) in substs.iter().enumerate() {
229253
let i = i.try_into().unwrap();
230254
if !unused.contains(i).unwrap_or(false) {
231255
arg.visit_with(self);
232256
}
233257
}
234-
debug!("visit_child_body: unused_parameters={:?}", self.unused_parameters);
258+
debug!(?self.unused_parameters);
235259
}
236260
}
237261

238262
impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
263+
#[instrument(skip(self, local))]
239264
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
240-
debug!("visit_local_decl: local_decl={:?}", local_decl);
241265
if local == Local::from_usize(1) {
242266
let def_kind = self.tcx.def_kind(self.def_id);
243267
if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
244268
// Skip visiting the closure/generator that is currently being processed. This only
245269
// happens because the first argument to the closure is a reference to itself and
246270
// that will call `visit_substs`, resulting in each generic parameter captured being
247271
// considered used by default.
248-
debug!("visit_local_decl: skipping closure substs");
272+
debug!("skipping closure substs");
249273
return;
250274
}
251275
}
@@ -263,15 +287,15 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
263287
}
264288

265289
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
290+
#[instrument(skip(self))]
266291
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
267-
debug!("visit_const: c={:?}", c);
268292
if !c.has_param_types_or_consts() {
269293
return ControlFlow::CONTINUE;
270294
}
271295

272296
match c.val {
273297
ty::ConstKind::Param(param) => {
274-
debug!("visit_const: param={:?}", param);
298+
debug!(?param);
275299
self.unused_parameters.clear(param.index);
276300
ControlFlow::CONTINUE
277301
}
@@ -296,15 +320,15 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
296320
}
297321
}
298322

323+
#[instrument(skip(self))]
299324
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
300-
debug!("visit_ty: ty={:?}", ty);
301325
if !ty.has_param_types_or_consts() {
302326
return ControlFlow::CONTINUE;
303327
}
304328

305329
match *ty.kind() {
306330
ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
307-
debug!("visit_ty: def_id={:?}", def_id);
331+
debug!(?def_id);
308332
// Avoid cycle errors with generators.
309333
if def_id == self.def_id {
310334
return ControlFlow::CONTINUE;
@@ -316,7 +340,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
316340
ControlFlow::CONTINUE
317341
}
318342
ty::Param(param) => {
319-
debug!("visit_ty: param={:?}", param);
343+
debug!(?param);
320344
self.unused_parameters.clear(param.index);
321345
ControlFlow::CONTINUE
322346
}
@@ -333,8 +357,8 @@ struct HasUsedGenericParams<'a> {
333357
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
334358
type BreakTy = ();
335359

360+
#[instrument(skip(self))]
336361
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
337-
debug!("visit_const: c={:?}", c);
338362
if !c.has_param_types_or_consts() {
339363
return ControlFlow::CONTINUE;
340364
}
@@ -351,8 +375,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
351375
}
352376
}
353377

378+
#[instrument(skip(self))]
354379
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
355-
debug!("visit_ty: ty={:?}", ty);
356380
if !ty.has_param_types_or_consts() {
357381
return ControlFlow::CONTINUE;
358382
}

‎src/doc/rustdoc/src/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
- [Documentation tests](documentation-tests.md)
99
- [Linking to items by name](linking-to-items-by-name.md)
1010
- [Lints](lints.md)
11-
- [Passes](passes.md)
1211
- [Advanced features](advanced-features.md)
1312
- [Unstable features](unstable-features.md)
13+
- [Passes](passes.md)
1414
- [References](references.md)

‎src/doc/rustdoc/src/command-line-arguments.md

+37-49
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,6 @@ release: 1.17.0
5757
LLVM version: 3.9
5858
```
5959

60-
## `-r`/`--input-format`: input format
61-
62-
This flag is currently ignored; the idea is that `rustdoc` would support various
63-
input formats, and you could specify them via this flag.
64-
65-
Rustdoc only supports Rust source code and Markdown input formats. If the
66-
file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
67-
Otherwise, it assumes that the input file is Rust.
68-
69-
70-
## `-w`/`--output-format`: output format
71-
72-
This flag is currently ignored; the idea is that `rustdoc` would support
73-
various output formats, and you could specify them via this flag.
74-
75-
Rustdoc only supports HTML output, and so this flag is redundant today.
76-
7760
## `-o`/`--output`: output path
7861

7962
Using this flag looks like this:
@@ -100,6 +83,25 @@ By default, `rustdoc` assumes that the name of your crate is the same name
10083
as the `.rs` file. `--crate-name` lets you override this assumption with
10184
whatever name you choose.
10285

86+
## `--document-private-items`: Show items that are not public
87+
88+
Using this flag looks like this:
89+
90+
```bash
91+
$ rustdoc src/lib.rs --document-private-items
92+
```
93+
94+
By default, `rustdoc` only documents items that are publicly reachable.
95+
96+
```rust
97+
pub fn public() {} // this item is public and will documented
98+
mod private { // this item is private and will not be documented
99+
pub fn unreachable() {} // this item is public, but unreachable, so it will not be documented
100+
}
101+
```
102+
103+
`--document-private-items` documents all items, even if they're not public.
104+
103105
## `-L`/`--library-path`: where to look for dependencies
104106

105107
Using this flag looks like this:
@@ -166,38 +168,6 @@ affect that.
166168
The arguments to this flag are the same as those for the `-C` flag on rustc. Run `rustc -C help` to
167169
get the full list.
168170

169-
## `--passes`: add more rustdoc passes
170-
171-
Using this flag looks like this:
172-
173-
```bash
174-
$ rustdoc --passes list
175-
$ rustdoc src/lib.rs --passes strip-priv-imports
176-
```
177-
178-
An argument of "list" will print a list of possible "rustdoc passes", and other
179-
arguments will be the name of which passes to run in addition to the defaults.
180-
181-
For more details on passes, see [the chapter on them](passes.md).
182-
183-
See also `--no-defaults`.
184-
185-
## `--no-defaults`: don't run default passes
186-
187-
Using this flag looks like this:
188-
189-
```bash
190-
$ rustdoc src/lib.rs --no-defaults
191-
```
192-
193-
By default, `rustdoc` will run several passes over your code. This
194-
removes those defaults, allowing you to use `--passes` to specify
195-
exactly which passes you want.
196-
197-
For more details on passes, see [the chapter on them](passes.md).
198-
199-
See also `--passes`.
200-
201171
## `--test`: run code examples as tests
202172

203173
Using this flag looks like this:
@@ -429,3 +399,21 @@ If you specify `@path` on the command-line, then it will open `path` and read
429399
command line options from it. These options are one per line; a blank line indicates
430400
an empty option. The file can use Unix or Windows style line endings, and must be
431401
encoded as UTF-8.
402+
403+
## `--passes`: add more rustdoc passes
404+
405+
This flag is **deprecated**.
406+
For more details on passes, see [the chapter on them](passes.md).
407+
408+
## `--no-defaults`: don't run default passes
409+
410+
This flag is **deprecated**.
411+
For more details on passes, see [the chapter on them](passes.md).
412+
413+
## `-r`/`--input-format`: input format
414+
415+
This flag is **deprecated** and **has no effect**.
416+
417+
Rustdoc only supports Rust source code and Markdown input formats. If the
418+
file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
419+
Otherwise, it assumes that the input file is Rust.

‎src/doc/rustdoc/src/passes.md

+5-82
Original file line numberDiff line numberDiff line change
@@ -3,86 +3,9 @@
33
Rustdoc has a concept called "passes". These are transformations that
44
`rustdoc` runs on your documentation before producing its final output.
55

6-
In addition to the passes below, check out the docs for these flags:
6+
Customizing passes is **deprecated**. The available passes are not considered stable and may
7+
change in any release.
78

8-
* [`--passes`](command-line-arguments.md#--passes-add-more-rustdoc-passes)
9-
* [`--no-defaults`](command-line-arguments.md#--no-defaults-dont-run-default-passes)
10-
11-
## Default passes
12-
13-
By default, rustdoc will run some passes, namely:
14-
15-
* `strip-hidden`
16-
* `strip-private`
17-
* `collapse-docs`
18-
* `unindent-comments`
19-
20-
However, `strip-private` implies `strip-priv-imports`, and so effectively,
21-
all passes are run by default.
22-
23-
## `strip-hidden`
24-
25-
This pass implements the `#[doc(hidden)]` attribute. When this pass runs, it
26-
checks each item, and if it is annotated with this attribute, it removes it
27-
from `rustdoc`'s output.
28-
29-
Without this pass, these items will remain in the output.
30-
31-
## `unindent-comments`
32-
33-
When you write a doc comment like this:
34-
35-
```rust,no_run
36-
/// This is a documentation comment.
37-
# fn f() {}
38-
```
39-
40-
There's a space between the `///` and that `T`. That spacing isn't intended
41-
to be a part of the output; it's there for humans, to help separate the doc
42-
comment syntax from the text of the comment. This pass is what removes that
43-
space.
44-
45-
The exact rules are left under-specified so that we can fix issues that we find.
46-
47-
Without this pass, the exact number of spaces is preserved.
48-
49-
## `collapse-docs`
50-
51-
With this pass, multiple `#[doc]` attributes are converted into one single
52-
documentation string.
53-
54-
For example:
55-
56-
```rust,no_run
57-
#[doc = "This is the first line."]
58-
#[doc = "This is the second line."]
59-
# fn f() {}
60-
```
61-
62-
Gets collapsed into a single doc string of
63-
64-
```text
65-
This is the first line.
66-
This is the second line.
67-
```
68-
69-
## `strip-private`
70-
71-
This removes documentation for any non-public items, so for example:
72-
73-
```rust,no_run
74-
/// These are private docs.
75-
struct Private;
76-
77-
/// These are public docs.
78-
pub struct Public;
79-
```
80-
81-
This pass removes the docs for `Private`, since they're not public.
82-
83-
This pass implies `strip-priv-imports`.
84-
85-
## `strip-priv-imports`
86-
87-
This is the same as `strip-private`, but for `extern crate` and `use`
88-
statements instead of items.
9+
In the past the most common use case for customizing passes was to omit the `strip-private` pass.
10+
You can do this more easily, and without risk of the pass being changed, by passing
11+
[`--document-private-items`](./unstable-features.md#--document-private-items).

‎src/doc/rustdoc/src/unstable-features.md

+24
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,30 @@ Some methodology notes about what rustdoc counts in this metric:
340340
Public items that are not documented can be seen with the built-in `missing_docs` lint. Private
341341
items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint.
342342

343+
## `-w`/`--output-format`: output format
344+
345+
When using
346+
[`--show-coverage`](https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--show-coverage-get-statistics-about-code-documentation-coverage),
347+
passing `--output-format json` will display the coverage information in JSON format. For example,
348+
here is the JSON for a file with one documented item and one undocumented item:
349+
350+
```rust
351+
/// This item has documentation
352+
pub fn foo() {}
353+
354+
pub fn no_documentation() {}
355+
```
356+
357+
```json
358+
{"no_std.rs":{"total":3,"with_docs":1,"total_examples":3,"with_examples":0}}
359+
```
360+
361+
Note that the third item is the crate root, which in this case is undocumented.
362+
363+
When not using `--show-coverage`, `--output-format json` emits documentation in the experimental
364+
[JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect,
365+
and is also accepted on stable toolchains.
366+
343367
### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
344368

345369
Using this flag looks like this:

‎src/librustdoc/html/render/context.rs

+617
Large diffs are not rendered by default.

‎src/librustdoc/html/render/mod.rs

+128-2,643
Large diffs are not rendered by default.

‎src/librustdoc/html/render/print_item.rs

+1,420
Large diffs are not rendered by default.

‎src/librustdoc/html/render/tests.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use super::*;
1+
use std::cmp::Ordering;
2+
3+
use super::print_item::compare_names;
4+
use super::{AllTypes, Buffer};
25

36
#[test]
47
fn test_compare_names() {

‎src/librustdoc/html/render/write_shared.rs

+542
Large diffs are not rendered by default.

‎src/librustdoc/passes/doc_test_lints.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ use crate::clean::*;
99
use crate::core::DocContext;
1010
use crate::fold::DocFolder;
1111
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
12+
use crate::visit_ast::inherits_doc_hidden;
1213
use rustc_middle::lint::LintLevelSource;
1314
use rustc_session::lint;
15+
use rustc_span::symbol::sym;
1416

1517
crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
1618
name: "check-private-items-doc-tests",
@@ -51,23 +53,30 @@ impl crate::doctest::Tester for Tests {
5153
}
5254

5355
crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
54-
if matches!(
55-
*item.kind,
56-
clean::StructFieldItem(_)
57-
| clean::VariantItem(_)
58-
| clean::AssocConstItem(_, _)
59-
| clean::AssocTypeItem(_, _)
60-
| clean::TypedefItem(_, _)
61-
| clean::StaticItem(_)
62-
| clean::ConstantItem(_)
63-
| clean::ExternCrateItem(_, _)
64-
| clean::ImportItem(_)
65-
| clean::PrimitiveItem(_)
66-
| clean::KeywordItem(_)
67-
) {
56+
if !cx.cache.access_levels.is_public(item.def_id)
57+
|| matches!(
58+
*item.kind,
59+
clean::StructFieldItem(_)
60+
| clean::VariantItem(_)
61+
| clean::AssocConstItem(_, _)
62+
| clean::AssocTypeItem(_, _)
63+
| clean::TypedefItem(_, _)
64+
| clean::StaticItem(_)
65+
| clean::ConstantItem(_)
66+
| clean::ExternCrateItem(_, _)
67+
| clean::ImportItem(_)
68+
| clean::PrimitiveItem(_)
69+
| clean::KeywordItem(_)
70+
)
71+
{
6872
return false;
6973
}
7074
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
75+
if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
76+
|| inherits_doc_hidden(cx.tcx, hir_id)
77+
{
78+
return false;
79+
}
7180
let (level, source) = cx.tcx.lint_level_at_node(crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id);
7281
level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
7382
}

‎src/librustdoc/visit_ast.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
2929
std::iter::once(crate_name).chain(relative).collect()
3030
}
3131

32+
crate fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool {
33+
while let Some(id) = tcx.hir().get_enclosing_scope(node) {
34+
node = id;
35+
if tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
36+
return true;
37+
}
38+
}
39+
false
40+
}
41+
3242
// Also, is there some reason that this doesn't use the 'visit'
3343
// framework from syntax?.
3444

@@ -158,19 +168,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
158168
om: &mut Module<'tcx>,
159169
please_inline: bool,
160170
) -> bool {
161-
fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool {
162-
while let Some(id) = cx.tcx.hir().get_enclosing_scope(node) {
163-
node = id;
164-
if cx.tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
165-
return true;
166-
}
167-
if node == hir::CRATE_HIR_ID {
168-
break;
169-
}
170-
}
171-
false
172-
}
173-
174171
debug!("maybe_inline_local res: {:?}", res);
175172

176173
let tcx = self.cx.tcx;
@@ -212,7 +209,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
212209
};
213210

214211
let is_private = !self.cx.cache.access_levels.is_public(res_did);
215-
let is_hidden = inherits_doc_hidden(self.cx, res_hir_id);
212+
let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id);
216213

217214
// Only inline if requested or if the item would otherwise be stripped.
218215
if (!please_inline && !is_private && !is_hidden) || is_no_inline {

‎src/test/rustdoc-ui/lint-missing-doc-code-example.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
/// ```
1313
/// println!("hello");
1414
/// ```
15-
fn test() {
15+
pub fn test() {
1616
}
1717

1818
#[allow(missing_docs)]
19-
mod module1 { //~ ERROR
19+
pub mod module1 { //~ ERROR
2020
}
2121

2222
#[allow(rustdoc::missing_doc_code_examples)]
2323
/// doc
24-
mod module2 {
24+
pub mod module2 {
2525

2626
/// doc
2727
pub fn test() {}
@@ -63,9 +63,22 @@ pub enum Enum {
6363
/// Doc
6464
//~^ ERROR
6565
#[repr(C)]
66-
union Union {
66+
pub union Union {
6767
/// Doc, but no code example and it's fine!
6868
a: i32,
6969
/// Doc, but no code example and it's fine!
7070
b: f32,
7171
}
72+
73+
74+
#[doc(hidden)]
75+
pub mod foo {
76+
pub fn bar() {}
77+
}
78+
79+
fn babar() {}
80+
81+
82+
mod fofoo {
83+
pub fn tadam() {}
84+
}

‎src/test/rustdoc-ui/lint-missing-doc-code-example.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error: missing code example in this documentation
22
--> $DIR/lint-missing-doc-code-example.rs:19:1
33
|
4-
LL | / mod module1 {
4+
LL | / pub mod module1 {
55
LL | | }
66
| |_^
77
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Regression test for #81712.
2+
3+
#![feature(generic_associated_types)]
4+
#![allow(incomplete_features)]
5+
6+
trait A {
7+
type BType: B<AType = Self>;
8+
}
9+
10+
trait B {
11+
type AType: A<BType = Self>;
12+
}
13+
trait C {
14+
type DType<T>: D<T, CType = Self>;
15+
//~^ ERROR: missing generics for associated type `C::DType` [E0107]
16+
}
17+
trait D<T> {
18+
type CType: C<DType = Self>;
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0107]: missing generics for associated type `C::DType`
2+
--> $DIR/issue-81712-cyclic-traits.rs:14:10
3+
|
4+
LL | type DType<T>: D<T, CType = Self>;
5+
| ^^^^^ expected 1 type argument
6+
|
7+
note: associated type defined here, with 1 type parameter: `T`
8+
--> $DIR/issue-81712-cyclic-traits.rs:14:10
9+
|
10+
LL | type DType<T>: D<T, CType = Self>;
11+
| ^^^^^ -
12+
help: use angle brackets to add missing type argument
13+
|
14+
LL | type DType<T><T>: D<T, CType = Self>;
15+
| ^^^
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)
Please sign in to comment.