Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e1b8898

Browse files
committedMar 9, 2019
Auto merge of #57882 - euclio:unused-doc-attributes, r=estebank
overhaul unused doc comments lint This PR contains a number of improvements to the `unused_doc_comments` lint. - Extends the span to cover the entire comment when using sugared doc comments. - Triggers the lint for all unused doc comments on a node, instead of just the first one. - Triggers the lint on macro expansions, and provides a help note explaining that doc comments must be expanded by the macro. - Adds a label pointing at the node that cannot be documented. Furthermore, this PR fixes any instances in rustc where a macro expansion was erroneously documented.
2 parents c9f8304 + daf80f7 commit e1b8898

File tree

14 files changed

+342
-163
lines changed

14 files changed

+342
-163
lines changed
 

‎src/libcore/num/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4515,7 +4515,7 @@ macro_rules! rev {
45154515
)*}
45164516
}
45174517

4518-
/// intra-sign conversions
4518+
// intra-sign conversions
45194519
try_from_upper_bounded!(u16, u8);
45204520
try_from_upper_bounded!(u32, u16, u8);
45214521
try_from_upper_bounded!(u64, u32, u16, u8);

‎src/librustc/hir/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ impl fmt::Display for HirId {
122122
// hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module
123123
mod item_local_id_inner {
124124
use rustc_data_structures::indexed_vec::Idx;
125-
/// An `ItemLocalId` uniquely identifies something within a given "item-like",
126-
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
127-
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
128-
/// the node's position within the owning item in any way, but there is a
129-
/// guarantee that the `LocalItemId`s within an owner occupy a dense range of
130-
/// integers starting at zero, so a mapping that maps all or most nodes within
131-
/// an "item-like" to something else can be implement by a `Vec` instead of a
132-
/// tree or hash map.
133125
newtype_index! {
126+
/// An `ItemLocalId` uniquely identifies something within a given "item-like",
127+
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
128+
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
129+
/// the node's position within the owning item in any way, but there is a
130+
/// guarantee that the `LocalItemId`s within an owner occupy a dense range of
131+
/// integers starting at zero, so a mapping that maps all or most nodes within
132+
/// an "item-like" to something else can be implement by a `Vec` instead of a
133+
/// tree or hash map.
134134
pub struct ItemLocalId { .. }
135135
}
136136
}

‎src/librustc/middle/region.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -132,25 +132,24 @@ pub enum ScopeData {
132132
Remainder(FirstStatementIndex)
133133
}
134134

135-
/// Represents a subscope of `block` for a binding that is introduced
136-
/// by `block.stmts[first_statement_index]`. Such subscopes represent
137-
/// a suffix of the block. Note that each subscope does not include
138-
/// the initializer expression, if any, for the statement indexed by
139-
/// `first_statement_index`.
140-
///
141-
/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`:
142-
///
143-
/// * The subscope with `first_statement_index == 0` is scope of both
144-
/// `a` and `b`; it does not include EXPR_1, but does include
145-
/// everything after that first `let`. (If you want a scope that
146-
/// includes EXPR_1 as well, then do not use `Scope::Remainder`,
147-
/// but instead another `Scope` that encompasses the whole block,
148-
/// e.g., `Scope::Node`.
149-
///
150-
/// * The subscope with `first_statement_index == 1` is scope of `c`,
151-
/// and thus does not include EXPR_2, but covers the `...`.
152-
153135
newtype_index! {
136+
/// Represents a subscope of `block` for a binding that is introduced
137+
/// by `block.stmts[first_statement_index]`. Such subscopes represent
138+
/// a suffix of the block. Note that each subscope does not include
139+
/// the initializer expression, if any, for the statement indexed by
140+
/// `first_statement_index`.
141+
///
142+
/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`:
143+
///
144+
/// * The subscope with `first_statement_index == 0` is scope of both
145+
/// `a` and `b`; it does not include EXPR_1, but does include
146+
/// everything after that first `let`. (If you want a scope that
147+
/// includes EXPR_1 as well, then do not use `Scope::Remainder`,
148+
/// but instead another `Scope` that encompasses the whole block,
149+
/// e.g., `Scope::Node`.
150+
///
151+
/// * The subscope with `first_statement_index == 1` is scope of `c`,
152+
/// and thus does not include EXPR_2, but covers the `...`.
154153
pub struct FirstStatementIndex { .. }
155154
}
156155

‎src/librustc/ty/context.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,9 +1892,11 @@ pub mod tls {
18921892
rayon_core::tlv::get()
18931893
}
18941894

1895-
/// A thread local variable which stores a pointer to the current ImplicitCtxt
18961895
#[cfg(not(parallel_compiler))]
1897-
thread_local!(static TLV: Cell<usize> = Cell::new(0));
1896+
thread_local! {
1897+
/// A thread local variable which stores a pointer to the current ImplicitCtxt.
1898+
static TLV: Cell<usize> = Cell::new(0);
1899+
}
18981900

18991901
/// Sets TLV to `value` during the call to `f`.
19001902
/// It is restored to its previous value after.
@@ -2011,10 +2013,11 @@ pub mod tls {
20112013
})
20122014
}
20132015

2014-
/// Stores a pointer to the GlobalCtxt if one is available.
2015-
/// This is used to access the GlobalCtxt in the deadlock handler
2016-
/// given to Rayon.
2017-
scoped_thread_local!(pub static GCX_PTR: Lock<usize>);
2016+
scoped_thread_local! {
2017+
/// Stores a pointer to the GlobalCtxt if one is available.
2018+
/// This is used to access the GlobalCtxt in the deadlock handler given to Rayon.
2019+
pub static GCX_PTR: Lock<usize>
2020+
}
20182021

20192022
/// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
20202023
/// This is used in the deadlock handler.

‎src/librustc/ty/mod.rs

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,42 +1512,42 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
15121512
}
15131513
}
15141514

1515-
/// "Universes" are used during type- and trait-checking in the
1516-
/// presence of `for<..>` binders to control what sets of names are
1517-
/// visible. Universes are arranged into a tree: the root universe
1518-
/// contains names that are always visible. Each child then adds a new
1519-
/// set of names that are visible, in addition to those of its parent.
1520-
/// We say that the child universe "extends" the parent universe with
1521-
/// new names.
1522-
///
1523-
/// To make this more concrete, consider this program:
1524-
///
1525-
/// ```
1526-
/// struct Foo { }
1527-
/// fn bar<T>(x: T) {
1528-
/// let y: for<'a> fn(&'a u8, Foo) = ...;
1529-
/// }
1530-
/// ```
1531-
///
1532-
/// The struct name `Foo` is in the root universe U0. But the type
1533-
/// parameter `T`, introduced on `bar`, is in an extended universe U1
1534-
/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
1535-
/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
1536-
/// region `'a` is in a universe U2 that extends U1, because we can
1537-
/// name it inside the fn type but not outside.
1538-
///
1539-
/// Universes are used to do type- and trait-checking around these
1540-
/// "forall" binders (also called **universal quantification**). The
1541-
/// idea is that when, in the body of `bar`, we refer to `T` as a
1542-
/// type, we aren't referring to any type in particular, but rather a
1543-
/// kind of "fresh" type that is distinct from all other types we have
1544-
/// actually declared. This is called a **placeholder** type, and we
1545-
/// use universes to talk about this. In other words, a type name in
1546-
/// universe 0 always corresponds to some "ground" type that the user
1547-
/// declared, but a type name in a non-zero universe is a placeholder
1548-
/// type -- an idealized representative of "types in general" that we
1549-
/// use for checking generic functions.
15501515
newtype_index! {
1516+
/// "Universes" are used during type- and trait-checking in the
1517+
/// presence of `for<..>` binders to control what sets of names are
1518+
/// visible. Universes are arranged into a tree: the root universe
1519+
/// contains names that are always visible. Each child then adds a new
1520+
/// set of names that are visible, in addition to those of its parent.
1521+
/// We say that the child universe "extends" the parent universe with
1522+
/// new names.
1523+
///
1524+
/// To make this more concrete, consider this program:
1525+
///
1526+
/// ```
1527+
/// struct Foo { }
1528+
/// fn bar<T>(x: T) {
1529+
/// let y: for<'a> fn(&'a u8, Foo) = ...;
1530+
/// }
1531+
/// ```
1532+
///
1533+
/// The struct name `Foo` is in the root universe U0. But the type
1534+
/// parameter `T`, introduced on `bar`, is in an extended universe U1
1535+
/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
1536+
/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
1537+
/// region `'a` is in a universe U2 that extends U1, because we can
1538+
/// name it inside the fn type but not outside.
1539+
///
1540+
/// Universes are used to do type- and trait-checking around these
1541+
/// "forall" binders (also called **universal quantification**). The
1542+
/// idea is that when, in the body of `bar`, we refer to `T` as a
1543+
/// type, we aren't referring to any type in particular, but rather a
1544+
/// kind of "fresh" type that is distinct from all other types we have
1545+
/// actually declared. This is called a **placeholder** type, and we
1546+
/// use universes to talk about this. In other words, a type name in
1547+
/// universe 0 always corresponds to some "ground" type that the user
1548+
/// declared, but a type name in a non-zero universe is a placeholder
1549+
/// type -- an idealized representative of "types in general" that we
1550+
/// use for checking generic functions.
15511551
pub struct UniverseIndex {
15521552
DEBUG_FORMAT = "U{}",
15531553
}

‎src/librustc/ty/sty.rs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,46 +1082,46 @@ impl<'a, 'gcx, 'tcx> ParamConst {
10821082
}
10831083
}
10841084

1085-
/// A [De Bruijn index][dbi] is a standard means of representing
1086-
/// regions (and perhaps later types) in a higher-ranked setting. In
1087-
/// particular, imagine a type like this:
1088-
///
1089-
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
1090-
/// ^ ^ | | |
1091-
/// | | | | |
1092-
/// | +------------+ 0 | |
1093-
/// | | |
1094-
/// +--------------------------------+ 1 |
1095-
/// | |
1096-
/// +------------------------------------------+ 0
1097-
///
1098-
/// In this type, there are two binders (the outer fn and the inner
1099-
/// fn). We need to be able to determine, for any given region, which
1100-
/// fn type it is bound by, the inner or the outer one. There are
1101-
/// various ways you can do this, but a De Bruijn index is one of the
1102-
/// more convenient and has some nice properties. The basic idea is to
1103-
/// count the number of binders, inside out. Some examples should help
1104-
/// clarify what I mean.
1105-
///
1106-
/// Let's start with the reference type `&'b isize` that is the first
1107-
/// argument to the inner function. This region `'b` is assigned a De
1108-
/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
1109-
/// fn). The region `'a` that appears in the second argument type (`&'a
1110-
/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
1111-
/// second-innermost binder". (These indices are written on the arrays
1112-
/// in the diagram).
1113-
///
1114-
/// What is interesting is that De Bruijn index attached to a particular
1115-
/// variable will vary depending on where it appears. For example,
1116-
/// the final type `&'a char` also refers to the region `'a` declared on
1117-
/// the outermost fn. But this time, this reference is not nested within
1118-
/// any other binders (i.e., it is not an argument to the inner fn, but
1119-
/// rather the outer one). Therefore, in this case, it is assigned a
1120-
/// De Bruijn index of 0, because the innermost binder in that location
1121-
/// is the outer fn.
1122-
///
1123-
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
11241085
newtype_index! {
1086+
/// A [De Bruijn index][dbi] is a standard means of representing
1087+
/// regions (and perhaps later types) in a higher-ranked setting. In
1088+
/// particular, imagine a type like this:
1089+
///
1090+
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
1091+
/// ^ ^ | | |
1092+
/// | | | | |
1093+
/// | +------------+ 0 | |
1094+
/// | | |
1095+
/// +--------------------------------+ 1 |
1096+
/// | |
1097+
/// +------------------------------------------+ 0
1098+
///
1099+
/// In this type, there are two binders (the outer fn and the inner
1100+
/// fn). We need to be able to determine, for any given region, which
1101+
/// fn type it is bound by, the inner or the outer one. There are
1102+
/// various ways you can do this, but a De Bruijn index is one of the
1103+
/// more convenient and has some nice properties. The basic idea is to
1104+
/// count the number of binders, inside out. Some examples should help
1105+
/// clarify what I mean.
1106+
///
1107+
/// Let's start with the reference type `&'b isize` that is the first
1108+
/// argument to the inner function. This region `'b` is assigned a De
1109+
/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
1110+
/// fn). The region `'a` that appears in the second argument type (`&'a
1111+
/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
1112+
/// second-innermost binder". (These indices are written on the arrays
1113+
/// in the diagram).
1114+
///
1115+
/// What is interesting is that De Bruijn index attached to a particular
1116+
/// variable will vary depending on where it appears. For example,
1117+
/// the final type `&'a char` also refers to the region `'a` declared on
1118+
/// the outermost fn. But this time, this reference is not nested within
1119+
/// any other binders (i.e., it is not an argument to the inner fn, but
1120+
/// rather the outer one). Therefore, in this case, it is assigned a
1121+
/// De Bruijn index of 0, because the innermost binder in that location
1122+
/// is the outer fn.
1123+
///
1124+
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
11251125
pub struct DebruijnIndex {
11261126
DEBUG_FORMAT = "DebruijnIndex({})",
11271127
const INNERMOST = 0,

‎src/librustc_data_structures/indexed_vec.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ macro_rules! newtype_index {
5858
// ---- public rules ----
5959

6060
// Use default constants
61-
($v:vis struct $name:ident { .. }) => (
61+
($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => (
6262
newtype_index!(
6363
// Leave out derives marker so we can use its absence to ensure it comes first
64+
@attrs [$(#[$attrs])*]
6465
@type [$name]
6566
// shave off 256 indices at the end to allow space for packing these indices into enums
6667
@max [0xFFFF_FF00]
@@ -69,9 +70,10 @@ macro_rules! newtype_index {
6970
);
7071

7172
// Define any constants
72-
($v:vis struct $name:ident { $($tokens:tt)+ }) => (
73+
($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => (
7374
newtype_index!(
7475
// Leave out derives marker so we can use its absence to ensure it comes first
76+
@attrs [$(#[$attrs])*]
7577
@type [$name]
7678
// shave off 256 indices at the end to allow space for packing these indices into enums
7779
@max [0xFFFF_FF00]
@@ -84,10 +86,12 @@ macro_rules! newtype_index {
8486

8587
// Base case, user-defined constants (if any) have already been defined
8688
(@derives [$($derives:ident,)*]
89+
@attrs [$(#[$attrs:meta])*]
8790
@type [$type:ident]
8891
@max [$max:expr]
8992
@vis [$v:vis]
9093
@debug_format [$debug_format:tt]) => (
94+
$(#[$attrs])*
9195
#[derive(Copy, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
9296
#[rustc_layout_scalar_valid_range_end($max)]
9397
$v struct $type {
@@ -317,14 +321,16 @@ macro_rules! newtype_index {
317321

318322
// By not including the @derives marker in this list nor in the default args, we can force it
319323
// to come first if it exists. When encodable isn't custom, add serialization traits by default.
320-
(@type [$type:ident]
324+
(@attrs [$(#[$attrs:meta])*]
325+
@type [$type:ident]
321326
@max [$max:expr]
322327
@vis [$v:vis]
323328
@debug_format [$debug_format:tt]
324329
derive [$($derives:ident,)+]
325330
$($tokens:tt)*) => (
326331
newtype_index!(
327332
@derives [$($derives,)+ RustcEncodable,]
333+
@attrs [$(#[$attrs])*]
328334
@type [$type]
329335
@max [$max]
330336
@vis [$v]
@@ -335,14 +341,16 @@ macro_rules! newtype_index {
335341

336342
// The case where no derives are added, but encodable is overridden. Don't
337343
// derive serialization traits
338-
(@type [$type:ident]
344+
(@attrs [$(#[$attrs:meta])*]
345+
@type [$type:ident]
339346
@max [$max:expr]
340347
@vis [$v:vis]
341348
@debug_format [$debug_format:tt]
342349
ENCODABLE = custom
343350
$($tokens:tt)*) => (
344351
newtype_index!(
345352
@derives []
353+
@attrs [$(#[$attrs])*]
346354
@type [$type]
347355
@max [$max]
348356
@vis [$v]
@@ -351,13 +359,15 @@ macro_rules! newtype_index {
351359
);
352360

353361
// The case where no derives are added, add serialization derives by default
354-
(@type [$type:ident]
362+
(@attrs [$(#[$attrs:meta])*]
363+
@type [$type:ident]
355364
@max [$max:expr]
356365
@vis [$v:vis]
357366
@debug_format [$debug_format:tt]
358367
$($tokens:tt)*) => (
359368
newtype_index!(
360369
@derives [RustcEncodable,]
370+
@attrs [$(#[$attrs])*]
361371
@type [$type]
362372
@max [$max]
363373
@vis [$v]
@@ -384,13 +394,15 @@ macro_rules! newtype_index {
384394

385395
// Rewrite final without comma to one that includes comma
386396
(@derives [$($derives:ident,)*]
397+
@attrs [$(#[$attrs:meta])*]
387398
@type [$type:ident]
388399
@max [$max:expr]
389400
@vis [$v:vis]
390401
@debug_format [$debug_format:tt]
391402
$name:ident = $constant:expr) => (
392403
newtype_index!(
393404
@derives [$($derives,)*]
405+
@attrs [$(#[$attrs])*]
394406
@type [$type]
395407
@max [$max]
396408
@vis [$v]
@@ -400,6 +412,7 @@ macro_rules! newtype_index {
400412

401413
// Rewrite final const without comma to one that includes comma
402414
(@derives [$($derives:ident,)*]
415+
@attrs [$(#[$attrs:meta])*]
403416
@type [$type:ident]
404417
@max [$_max:expr]
405418
@vis [$v:vis]
@@ -408,6 +421,7 @@ macro_rules! newtype_index {
408421
const $name:ident = $constant:expr) => (
409422
newtype_index!(
410423
@derives [$($derives,)*]
424+
@attrs [$(#[$attrs])*]
411425
@type [$type]
412426
@max [$max]
413427
@vis [$v]
@@ -417,6 +431,7 @@ macro_rules! newtype_index {
417431

418432
// Replace existing default for max
419433
(@derives [$($derives:ident,)*]
434+
@attrs [$(#[$attrs:meta])*]
420435
@type [$type:ident]
421436
@max [$_max:expr]
422437
@vis [$v:vis]
@@ -425,6 +440,7 @@ macro_rules! newtype_index {
425440
$($tokens:tt)*) => (
426441
newtype_index!(
427442
@derives [$($derives,)*]
443+
@attrs [$(#[$attrs])*]
428444
@type [$type]
429445
@max [$max]
430446
@vis [$v]
@@ -434,6 +450,7 @@ macro_rules! newtype_index {
434450

435451
// Replace existing default for debug_format
436452
(@derives [$($derives:ident,)*]
453+
@attrs [$(#[$attrs:meta])*]
437454
@type [$type:ident]
438455
@max [$max:expr]
439456
@vis [$v:vis]
@@ -442,6 +459,7 @@ macro_rules! newtype_index {
442459
$($tokens:tt)*) => (
443460
newtype_index!(
444461
@derives [$($derives,)*]
462+
@attrs [$(#[$attrs])*]
445463
@type [$type]
446464
@max [$max]
447465
@vis [$v]
@@ -451,6 +469,7 @@ macro_rules! newtype_index {
451469

452470
// Assign a user-defined constant
453471
(@derives [$($derives:ident,)*]
472+
@attrs [$(#[$attrs:meta])*]
454473
@type [$type:ident]
455474
@max [$max:expr]
456475
@vis [$v:vis]
@@ -462,6 +481,7 @@ macro_rules! newtype_index {
462481
pub const $name: $type = $type::from_u32_const($constant);
463482
newtype_index!(
464483
@derives [$($derives,)*]
484+
@attrs [$(#[$attrs])*]
465485
@type [$type]
466486
@max [$max]
467487
@vis [$v]

‎src/librustc_lint/builtin.rs

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use syntax::tokenstream::{TokenTree, TokenStream};
3636
use syntax::ast;
3737
use syntax::ptr::P;
3838
use syntax::ast::Expr;
39-
use syntax::attr;
39+
use syntax::attr::{self, HasAttrs};
4040
use syntax::source_map::Spanned;
4141
use syntax::edition::Edition;
4242
use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
@@ -802,27 +802,81 @@ impl LintPass for UnusedDocComment {
802802
}
803803

804804
impl UnusedDocComment {
805-
fn warn_if_doc<'a, 'tcx,
806-
I: Iterator<Item=&'a ast::Attribute>,
807-
C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) {
808-
if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) {
809-
cx.struct_span_lint(UNUSED_DOC_COMMENTS, attr.span, "doc comment not used by rustdoc")
810-
.emit();
805+
fn warn_if_doc(
806+
&self,
807+
cx: &EarlyContext<'_>,
808+
node_span: Span,
809+
node_kind: &str,
810+
is_macro_expansion: bool,
811+
attrs: &[ast::Attribute]
812+
) {
813+
let mut attrs = attrs.into_iter().peekable();
814+
815+
// Accumulate a single span for sugared doc comments.
816+
let mut sugared_span: Option<Span> = None;
817+
818+
while let Some(attr) = attrs.next() {
819+
if attr.is_sugared_doc {
820+
sugared_span = Some(
821+
sugared_span.map_or_else(
822+
|| attr.span,
823+
|span| span.with_hi(attr.span.hi()),
824+
),
825+
);
826+
}
827+
828+
if attrs.peek().map(|next_attr| next_attr.is_sugared_doc).unwrap_or_default() {
829+
continue;
830+
}
831+
832+
let span = sugared_span.take().unwrap_or_else(|| attr.span);
833+
834+
if attr.name() == "doc" {
835+
let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment");
836+
837+
err.span_label(
838+
node_span,
839+
format!("rustdoc does not generate documentation for {}", node_kind)
840+
);
841+
842+
if is_macro_expansion {
843+
err.help("to document an item produced by a macro, \
844+
the macro must produce the documentation as part of its expansion");
845+
}
846+
847+
err.emit();
848+
}
811849
}
812850
}
813851
}
814852

815853
impl EarlyLintPass for UnusedDocComment {
816-
fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) {
817-
self.warn_if_doc(decl.attrs.iter(), cx);
854+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
855+
if let ast::ItemKind::Mac(..) = item.node {
856+
self.warn_if_doc(cx, item.span, "macro expansions", true, &item.attrs);
857+
}
858+
}
859+
860+
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
861+
let (kind, is_macro_expansion) = match stmt.node {
862+
ast::StmtKind::Local(..) => ("statements", false),
863+
ast::StmtKind::Item(..) => ("inner items", false),
864+
ast::StmtKind::Mac(..) => ("macro expansions", true),
865+
// expressions will be reported by `check_expr`.
866+
ast::StmtKind::Semi(..) |
867+
ast::StmtKind::Expr(..) => return,
868+
};
869+
870+
self.warn_if_doc(cx, stmt.span, kind, is_macro_expansion, stmt.node.attrs());
818871
}
819872

820873
fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
821-
self.warn_if_doc(arm.attrs.iter(), cx);
874+
let arm_span = arm.pats[0].span.with_hi(arm.body.span.hi());
875+
self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs);
822876
}
823877

824878
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
825-
self.warn_if_doc(expr.attrs.iter(), cx);
879+
self.warn_if_doc(cx, expr.span, "expressions", false, &expr.attrs);
826880
}
827881
}
828882

‎src/librustc_lint/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ macro_rules! pre_expansion_lint_passes {
6666
($macro:path, $args:tt) => (
6767
$macro!($args, [
6868
KeywordIdents: KeywordIdents,
69+
UnusedDocComment: UnusedDocComment,
6970
]);
7071
)
7172
}
@@ -77,7 +78,6 @@ macro_rules! early_lint_passes {
7778
UnusedImportBraces: UnusedImportBraces,
7879
UnsafeCode: UnsafeCode,
7980
AnonymousParameters: AnonymousParameters,
80-
UnusedDocComment: UnusedDocComment,
8181
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns,
8282
NonCamelCaseTypes: NonCamelCaseTypes,
8383
DeprecatedAttr: DeprecatedAttr::new(),

‎src/librustc_mir/borrow_check/nll/region_infer/values.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,14 @@ impl RegionValueElements {
116116
}
117117
}
118118

119-
/// A single integer representing a `Location` in the MIR control-flow
120-
/// graph. Constructed efficiently from `RegionValueElements`.
121119
newtype_index! {
120+
/// A single integer representing a `Location` in the MIR control-flow
121+
/// graph. Constructed efficiently from `RegionValueElements`.
122122
pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" }
123123
}
124124

125-
/// A single integer representing a `ty::Placeholder`.
126125
newtype_index! {
126+
/// A single integer representing a `ty::Placeholder`.
127127
pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
128128
}
129129

‎src/librustc_mir/dataflow/move_paths/mod.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub(crate) mod indexes {
2323
use rustc_data_structures::indexed_vec::Idx;
2424

2525
macro_rules! new_index {
26-
($Index:ident, $debug_name:expr) => {
26+
($(#[$attrs:meta])* $Index:ident, $debug_name:expr) => {
2727
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2828
pub struct $Index(NonZeroUsize);
2929

@@ -44,17 +44,29 @@ pub(crate) mod indexes {
4444
}
4545
}
4646

47-
/// Index into MovePathData.move_paths
48-
new_index!(MovePathIndex, "mp");
49-
50-
/// Index into MoveData.moves.
51-
new_index!(MoveOutIndex, "mo");
52-
53-
/// Index into MoveData.inits.
54-
new_index!(InitIndex, "in");
55-
56-
/// Index into Borrows.locations
57-
new_index!(BorrowIndex, "bw");
47+
new_index!(
48+
/// Index into MovePathData.move_paths
49+
MovePathIndex,
50+
"mp"
51+
);
52+
53+
new_index!(
54+
/// Index into MoveData.moves.
55+
MoveOutIndex,
56+
"mo"
57+
);
58+
59+
new_index!(
60+
/// Index into MoveData.inits.
61+
InitIndex,
62+
"in"
63+
);
64+
65+
new_index!(
66+
/// Index into Borrows.locations
67+
BorrowIndex,
68+
"bw"
69+
);
5870
}
5971

6072
pub use self::indexes::MovePathIndex;

‎src/libstd/io/stdio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ use crate::sys::stdio;
1111
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
1212
use crate::thread::LocalKey;
1313

14-
/// Stdout used by print! and println! macros
1514
thread_local! {
15+
/// Stdout used by print! and println! macros
1616
static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
1717
RefCell::new(None)
1818
}
1919
}
2020

21-
/// Stderr used by eprint! and eprintln! macros, and panics
2221
thread_local! {
22+
/// Stderr used by eprint! and eprintln! macros, and panics
2323
static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
2424
RefCell::new(None)
2525
}

‎src/test/ui/useless_comment.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,43 @@
1+
#![feature(stmt_expr_attributes)]
2+
13
#![deny(unused_doc_comments)]
24

5+
macro_rules! mac {
6+
() => {}
7+
}
8+
9+
/// foo //~ ERROR unused doc comment
10+
mac!();
11+
312
fn foo() {
4-
/// a //~ ERROR doc comment not used by rustdoc
13+
/// a //~ ERROR unused doc comment
514
let x = 12;
615

7-
/// b //~ doc comment not used by rustdoc
16+
/// multi-line //~ unused doc comment
17+
/// doc comment
18+
/// that is unused
819
match x {
9-
/// c //~ ERROR doc comment not used by rustdoc
20+
/// c //~ ERROR unused doc comment
1021
1 => {},
1122
_ => {}
1223
}
1324

14-
/// foo //~ ERROR doc comment not used by rustdoc
25+
/// foo //~ ERROR unused doc comment
1526
unsafe {}
27+
28+
#[doc = "foo"] //~ ERROR unused doc comment
29+
#[doc = "bar"] //~ ERROR unused doc comment
30+
3;
31+
32+
/// bar //~ ERROR unused doc comment
33+
mac!();
34+
35+
let x = /** comment */ 47; //~ ERROR unused doc comment
36+
37+
/// dox //~ ERROR unused doc comment
38+
{
39+
40+
}
1641
}
1742

1843
fn main() {

‎src/test/ui/useless_comment.stderr

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,98 @@
1-
error: doc comment not used by rustdoc
2-
--> $DIR/useless_comment.rs:4:5
1+
error: unused doc comment
2+
--> $DIR/useless_comment.rs:9:1
33
|
4-
LL | /// a //~ ERROR doc comment not used by rustdoc
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | /// foo //~ ERROR unused doc comment
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL | mac!();
7+
| ------- rustdoc does not generate documentation for macro expansions
68
|
79
note: lint level defined here
8-
--> $DIR/useless_comment.rs:1:9
10+
--> $DIR/useless_comment.rs:3:9
911
|
1012
LL | #![deny(unused_doc_comments)]
1113
| ^^^^^^^^^^^^^^^^^^^
14+
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
1215

13-
error: doc comment not used by rustdoc
14-
--> $DIR/useless_comment.rs:7:5
16+
error: unused doc comment
17+
--> $DIR/useless_comment.rs:13:5
1518
|
16-
LL | /// b //~ doc comment not used by rustdoc
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
LL | /// a //~ ERROR unused doc comment
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
LL | let x = 12;
22+
| ----------- rustdoc does not generate documentation for statements
1823

19-
error: doc comment not used by rustdoc
20-
--> $DIR/useless_comment.rs:9:9
24+
error: unused doc comment
25+
--> $DIR/useless_comment.rs:16:5
2126
|
22-
LL | /// c //~ ERROR doc comment not used by rustdoc
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
LL | / /// multi-line //~ unused doc comment
28+
LL | | /// doc comment
29+
LL | | /// that is unused
30+
| |______________________^
31+
LL | / match x {
32+
LL | | /// c //~ ERROR unused doc comment
33+
LL | | 1 => {},
34+
LL | | _ => {}
35+
LL | | }
36+
| |_____- rustdoc does not generate documentation for expressions
2437

25-
error: doc comment not used by rustdoc
26-
--> $DIR/useless_comment.rs:14:5
38+
error: unused doc comment
39+
--> $DIR/useless_comment.rs:20:9
2740
|
28-
LL | /// foo //~ ERROR doc comment not used by rustdoc
29-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
LL | /// c //~ ERROR unused doc comment
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43+
LL | 1 => {},
44+
| ------- rustdoc does not generate documentation for match arms
3045

31-
error: aborting due to 4 previous errors
46+
error: unused doc comment
47+
--> $DIR/useless_comment.rs:25:5
48+
|
49+
LL | /// foo //~ ERROR unused doc comment
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
LL | unsafe {}
52+
| --------- rustdoc does not generate documentation for expressions
53+
54+
error: unused doc comment
55+
--> $DIR/useless_comment.rs:28:5
56+
|
57+
LL | #[doc = "foo"] //~ ERROR unused doc comment
58+
| ^^^^^^^^^^^^^^
59+
LL | #[doc = "bar"] //~ ERROR unused doc comment
60+
LL | 3;
61+
| - rustdoc does not generate documentation for expressions
62+
63+
error: unused doc comment
64+
--> $DIR/useless_comment.rs:29:5
65+
|
66+
LL | #[doc = "bar"] //~ ERROR unused doc comment
67+
| ^^^^^^^^^^^^^^
68+
LL | 3;
69+
| - rustdoc does not generate documentation for expressions
70+
71+
error: unused doc comment
72+
--> $DIR/useless_comment.rs:32:5
73+
|
74+
LL | /// bar //~ ERROR unused doc comment
75+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76+
LL | mac!();
77+
| ------- rustdoc does not generate documentation for macro expansions
78+
|
79+
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
80+
81+
error: unused doc comment
82+
--> $DIR/useless_comment.rs:35:13
83+
|
84+
LL | let x = /** comment */ 47; //~ ERROR unused doc comment
85+
| ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
86+
87+
error: unused doc comment
88+
--> $DIR/useless_comment.rs:37:5
89+
|
90+
LL | /// dox //~ ERROR unused doc comment
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92+
LL | / {
93+
LL | |
94+
LL | | }
95+
| |_____- rustdoc does not generate documentation for expressions
96+
97+
error: aborting due to 10 previous errors
3298

0 commit comments

Comments
 (0)
Please sign in to comment.