diff --git a/config.toml.example b/config.toml.example index f45db37c33b86..b4ad15a823578 100644 --- a/config.toml.example +++ b/config.toml.example @@ -162,6 +162,9 @@ # Python interpreter to use for various tasks throughout the build, notably # rustdoc tests, the lldb python interpreter, and some dist bits and pieces. # Note that Python 2 is currently required. +# +# Defaults to python2.7, then python2. If neither executable can be found, then +# it defaults to the Python interpreter used to execute x.py. #python = "python2.7" # Force Cargo to check that Cargo.lock describes the precise dependency diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 119b38bcc99dc..c98d8b8ecf437 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -830,7 +830,7 @@ def main(): # x.py help ... if len(sys.argv) > 1 and sys.argv[1] == 'help': - sys.argv = sys.argv[:1] + [sys.argv[2], '-h'] + sys.argv[3:] + sys.argv = [sys.argv[0], '-h'] + sys.argv[2:] help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index ff4fb85bbfad3..4b9d0cc15d665 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -107,9 +107,9 @@ pub fn check(build: &mut Build) { } build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) - .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py .or_else(|| cmd_finder.maybe_have("python2.7")) .or_else(|| cmd_finder.maybe_have("python2")) + .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py .or_else(|| Some(cmd_finder.must_have("python"))); build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p)) diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index 2c651c90f82eb..fdc1c4fa0cc38 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -290,6 +290,8 @@ def render_element(i): def read_utf8_string(ptr_val, byte_count): + if byte_count == 0: + return '""' error = lldb.SBError() process = ptr_val.get_wrapped_value().GetProcess() data = process.ReadMemory(ptr_val.as_integer(), byte_count, error) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 5b7d5f45d9246..7a5badb487ecf 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4613,7 +4613,7 @@ macro_rules! rev { )*} } -/// intra-sign conversions +// intra-sign conversions try_from_upper_bounded!(u16, u8); try_from_upper_bounded!(u32, u16, u8); try_from_upper_bounded!(u64, u32, u16, u8); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index df02b91996f34..36c3e8d449e7d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -115,15 +115,15 @@ impl serialize::UseSpecializedDecodable for HirId { // hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module mod item_local_id_inner { use rustc_data_structures::indexed_vec::Idx; - /// An `ItemLocalId` uniquely identifies something within a given "item-like", - /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no - /// guarantee that the numerical value of a given `ItemLocalId` corresponds to - /// the node's position within the owning item in any way, but there is a - /// guarantee that the `LocalItemId`s within an owner occupy a dense range of - /// integers starting at zero, so a mapping that maps all or most nodes within - /// an "item-like" to something else can be implement by a `Vec` instead of a - /// tree or hash map. newtype_index! { + /// An `ItemLocalId` uniquely identifies something within a given "item-like", + /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no + /// guarantee that the numerical value of a given `ItemLocalId` corresponds to + /// the node's position within the owning item in any way, but there is a + /// guarantee that the `LocalItemId`s within an owner occupy a dense range of + /// integers starting at zero, so a mapping that maps all or most nodes within + /// an "item-like" to something else can be implement by a `Vec` instead of a + /// tree or hash map. pub struct ItemLocalId { .. } } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index fd188b33d7e1f..6527ed46cbc9e 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -132,25 +132,24 @@ pub enum ScopeData { Remainder(FirstStatementIndex) } -/// Represents a subscope of `block` for a binding that is introduced -/// by `block.stmts[first_statement_index]`. Such subscopes represent -/// a suffix of the block. Note that each subscope does not include -/// the initializer expression, if any, for the statement indexed by -/// `first_statement_index`. -/// -/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`: -/// -/// * The subscope with `first_statement_index == 0` is scope of both -/// `a` and `b`; it does not include EXPR_1, but does include -/// everything after that first `let`. (If you want a scope that -/// includes EXPR_1 as well, then do not use `Scope::Remainder`, -/// but instead another `Scope` that encompasses the whole block, -/// e.g., `Scope::Node`. -/// -/// * The subscope with `first_statement_index == 1` is scope of `c`, -/// and thus does not include EXPR_2, but covers the `...`. - newtype_index! { + /// Represents a subscope of `block` for a binding that is introduced + /// by `block.stmts[first_statement_index]`. Such subscopes represent + /// a suffix of the block. Note that each subscope does not include + /// the initializer expression, if any, for the statement indexed by + /// `first_statement_index`. + /// + /// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`: + /// + /// * The subscope with `first_statement_index == 0` is scope of both + /// `a` and `b`; it does not include EXPR_1, but does include + /// everything after that first `let`. (If you want a scope that + /// includes EXPR_1 as well, then do not use `Scope::Remainder`, + /// but instead another `Scope` that encompasses the whole block, + /// e.g., `Scope::Node`. + /// + /// * The subscope with `first_statement_index == 1` is scope of `c`, + /// and thus does not include EXPR_2, but covers the `...`. pub struct FirstStatementIndex { .. } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6bb3222512565..5313098bcc535 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1883,9 +1883,11 @@ pub mod tls { rayon_core::tlv::get() } - /// A thread local variable which stores a pointer to the current ImplicitCtxt #[cfg(not(parallel_compiler))] - thread_local!(static TLV: Cell = Cell::new(0)); + thread_local!( + /// A thread local variable which stores a pointer to the current ImplicitCtxt + static TLV: Cell = Cell::new(0) + ); /// Sets TLV to `value` during the call to `f`. /// It is restored to its previous value after. @@ -2002,10 +2004,15 @@ pub mod tls { }) } - /// Stores a pointer to the GlobalCtxt if one is available. - /// This is used to access the GlobalCtxt in the deadlock handler - /// given to Rayon. - scoped_thread_local!(pub static GCX_PTR: Lock); + scoped_thread_local! { + // FIXME: This should be a doc comment, but the macro does not allow attributes: + // https://github.com/alexcrichton/scoped-tls/pull/8 + // + // Stores a pointer to the GlobalCtxt if one is available. + // This is used to access the GlobalCtxt in the deadlock handler + // given to Rayon. + pub static GCX_PTR: Lock + } /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local. /// This is used in the deadlock handler. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 02e4fb12af5c9..eed9c3ed7ef95 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1489,42 +1489,42 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -/// "Universes" are used during type- and trait-checking in the -/// presence of `for<..>` binders to control what sets of names are -/// visible. Universes are arranged into a tree: the root universe -/// contains names that are always visible. Each child then adds a new -/// set of names that are visible, in addition to those of its parent. -/// We say that the child universe "extends" the parent universe with -/// new names. -/// -/// To make this more concrete, consider this program: -/// -/// ``` -/// struct Foo { } -/// fn bar(x: T) { -/// let y: for<'a> fn(&'a u8, Foo) = ...; -/// } -/// ``` -/// -/// The struct name `Foo` is in the root universe U0. But the type -/// parameter `T`, introduced on `bar`, is in an extended universe U1 -/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside -/// of `bar`, we cannot name `T`. Then, within the type of `y`, the -/// region `'a` is in a universe U2 that extends U1, because we can -/// name it inside the fn type but not outside. -/// -/// Universes are used to do type- and trait-checking around these -/// "forall" binders (also called **universal quantification**). The -/// idea is that when, in the body of `bar`, we refer to `T` as a -/// type, we aren't referring to any type in particular, but rather a -/// kind of "fresh" type that is distinct from all other types we have -/// actually declared. This is called a **placeholder** type, and we -/// use universes to talk about this. In other words, a type name in -/// universe 0 always corresponds to some "ground" type that the user -/// declared, but a type name in a non-zero universe is a placeholder -/// type -- an idealized representative of "types in general" that we -/// use for checking generic functions. newtype_index! { + /// "Universes" are used during type- and trait-checking in the + /// presence of `for<..>` binders to control what sets of names are + /// visible. Universes are arranged into a tree: the root universe + /// contains names that are always visible. Each child then adds a new + /// set of names that are visible, in addition to those of its parent. + /// We say that the child universe "extends" the parent universe with + /// new names. + /// + /// To make this more concrete, consider this program: + /// + /// ``` + /// struct Foo { } + /// fn bar(x: T) { + /// let y: for<'a> fn(&'a u8, Foo) = ...; + /// } + /// ``` + /// + /// The struct name `Foo` is in the root universe U0. But the type + /// parameter `T`, introduced on `bar`, is in an extended universe U1 + /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside + /// of `bar`, we cannot name `T`. Then, within the type of `y`, the + /// region `'a` is in a universe U2 that extends U1, because we can + /// name it inside the fn type but not outside. + /// + /// Universes are used to do type- and trait-checking around these + /// "forall" binders (also called **universal quantification**). The + /// idea is that when, in the body of `bar`, we refer to `T` as a + /// type, we aren't referring to any type in particular, but rather a + /// kind of "fresh" type that is distinct from all other types we have + /// actually declared. This is called a **placeholder** type, and we + /// use universes to talk about this. In other words, a type name in + /// universe 0 always corresponds to some "ground" type that the user + /// declared, but a type name in a non-zero universe is a placeholder + /// type -- an idealized representative of "types in general" that we + /// use for checking generic functions. pub struct UniverseIndex { DEBUG_FORMAT = "U{}", } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index dd382ec006bd7..deed7084f3a97 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1061,46 +1061,46 @@ impl<'a, 'gcx, 'tcx> ParamTy { } } -/// A [De Bruijn index][dbi] is a standard means of representing -/// regions (and perhaps later types) in a higher-ranked setting. In -/// particular, imagine a type like this: -/// -/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) -/// ^ ^ | | | -/// | | | | | -/// | +------------+ 0 | | -/// | | | -/// +--------------------------------+ 1 | -/// | | -/// +------------------------------------------+ 0 -/// -/// In this type, there are two binders (the outer fn and the inner -/// fn). We need to be able to determine, for any given region, which -/// fn type it is bound by, the inner or the outer one. There are -/// various ways you can do this, but a De Bruijn index is one of the -/// more convenient and has some nice properties. The basic idea is to -/// count the number of binders, inside out. Some examples should help -/// clarify what I mean. -/// -/// Let's start with the reference type `&'b isize` that is the first -/// argument to the inner function. This region `'b` is assigned a De -/// Bruijn index of 0, meaning "the innermost binder" (in this case, a -/// fn). The region `'a` that appears in the second argument type (`&'a -/// isize`) would then be assigned a De Bruijn index of 1, meaning "the -/// second-innermost binder". (These indices are written on the arrays -/// in the diagram). -/// -/// What is interesting is that De Bruijn index attached to a particular -/// variable will vary depending on where it appears. For example, -/// the final type `&'a char` also refers to the region `'a` declared on -/// the outermost fn. But this time, this reference is not nested within -/// any other binders (i.e., it is not an argument to the inner fn, but -/// rather the outer one). Therefore, in this case, it is assigned a -/// De Bruijn index of 0, because the innermost binder in that location -/// is the outer fn. -/// -/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index newtype_index! { + /// A [De Bruijn index][dbi] is a standard means of representing + /// regions (and perhaps later types) in a higher-ranked setting. In + /// particular, imagine a type like this: + /// + /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) + /// ^ ^ | | | + /// | | | | | + /// | +------------+ 0 | | + /// | | | + /// +--------------------------------+ 1 | + /// | | + /// +------------------------------------------+ 0 + /// + /// In this type, there are two binders (the outer fn and the inner + /// fn). We need to be able to determine, for any given region, which + /// fn type it is bound by, the inner or the outer one. There are + /// various ways you can do this, but a De Bruijn index is one of the + /// more convenient and has some nice properties. The basic idea is to + /// count the number of binders, inside out. Some examples should help + /// clarify what I mean. + /// + /// Let's start with the reference type `&'b isize` that is the first + /// argument to the inner function. This region `'b` is assigned a De + /// Bruijn index of 0, meaning "the innermost binder" (in this case, a + /// fn). The region `'a` that appears in the second argument type (`&'a + /// isize`) would then be assigned a De Bruijn index of 1, meaning "the + /// second-innermost binder". (These indices are written on the arrays + /// in the diagram). + /// + /// What is interesting is that De Bruijn index attached to a particular + /// variable will vary depending on where it appears. For example, + /// the final type `&'a char` also refers to the region `'a` declared on + /// the outermost fn. But this time, this reference is not nested within + /// any other binders (i.e., it is not an argument to the inner fn, but + /// rather the outer one). Therefore, in this case, it is assigned a + /// De Bruijn index of 0, because the innermost binder in that location + /// is the outer fn. + /// + /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index pub struct DebruijnIndex { DEBUG_FORMAT = "DebruijnIndex({})", const INNERMOST = 0, diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 09aec50e4bb11..1153c3e79bfd5 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -58,9 +58,10 @@ macro_rules! newtype_index { // ---- public rules ---- // Use default constants - ($v:vis struct $name:ident { .. }) => ( + ($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => ( newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first + @attrs [$(#[$attrs])*] @type [$name] // shave off 256 indices at the end to allow space for packing these indices into enums @max [0xFFFF_FF00] @@ -69,9 +70,10 @@ macro_rules! newtype_index { ); // Define any constants - ($v:vis struct $name:ident { $($tokens:tt)+ }) => ( + ($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => ( newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first + @attrs [$(#[$attrs])*] @type [$name] // shave off 256 indices at the end to allow space for packing these indices into enums @max [0xFFFF_FF00] @@ -84,10 +86,12 @@ macro_rules! newtype_index { // Base case, user-defined constants (if any) have already been defined (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$max:expr] @vis [$v:vis] @debug_format [$debug_format:tt]) => ( + $(#[$attrs])* #[derive(Copy, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] #[rustc_layout_scalar_valid_range_end($max)] $v struct $type { @@ -317,7 +321,8 @@ macro_rules! newtype_index { // By not including the @derives marker in this list nor in the default args, we can force it // to come first if it exists. When encodable isn't custom, add serialization traits by default. - (@type [$type:ident] + (@attrs [$(#[$attrs:meta])*] + @type [$type:ident] @max [$max:expr] @vis [$v:vis] @debug_format [$debug_format:tt] @@ -325,6 +330,7 @@ macro_rules! newtype_index { $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)+ RustcEncodable,] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -335,7 +341,8 @@ macro_rules! newtype_index { // The case where no derives are added, but encodable is overridden. Don't // derive serialization traits - (@type [$type:ident] + (@attrs [$(#[$attrs:meta])*] + @type [$type:ident] @max [$max:expr] @vis [$v:vis] @debug_format [$debug_format:tt] @@ -343,6 +350,7 @@ macro_rules! newtype_index { $($tokens:tt)*) => ( newtype_index!( @derives [] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -351,13 +359,15 @@ macro_rules! newtype_index { ); // The case where no derives are added, add serialization derives by default - (@type [$type:ident] + (@attrs [$(#[$attrs:meta])*] + @type [$type:ident] @max [$max:expr] @vis [$v:vis] @debug_format [$debug_format:tt] $($tokens:tt)*) => ( newtype_index!( @derives [RustcEncodable,] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -384,6 +394,7 @@ macro_rules! newtype_index { // Rewrite final without comma to one that includes comma (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$max:expr] @vis [$v:vis] @@ -391,6 +402,7 @@ macro_rules! newtype_index { $name:ident = $constant:expr) => ( newtype_index!( @derives [$($derives,)*] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -400,6 +412,7 @@ macro_rules! newtype_index { // Rewrite final const without comma to one that includes comma (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$_max:expr] @vis [$v:vis] @@ -408,6 +421,7 @@ macro_rules! newtype_index { const $name:ident = $constant:expr) => ( newtype_index!( @derives [$($derives,)*] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -417,6 +431,7 @@ macro_rules! newtype_index { // Replace existing default for max (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$_max:expr] @vis [$v:vis] @@ -425,6 +440,7 @@ macro_rules! newtype_index { $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)*] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -434,6 +450,7 @@ macro_rules! newtype_index { // Replace existing default for debug_format (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$max:expr] @vis [$v:vis] @@ -442,6 +459,7 @@ macro_rules! newtype_index { $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)*] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] @@ -451,6 +469,7 @@ macro_rules! newtype_index { // Assign a user-defined constant (@derives [$($derives:ident,)*] + @attrs [$(#[$attrs:meta])*] @type [$type:ident] @max [$max:expr] @vis [$v:vis] @@ -462,6 +481,7 @@ macro_rules! newtype_index { pub const $name: $type = $type::from_u32_const($constant); newtype_index!( @derives [$($derives,)*] + @attrs [$(#[$attrs])*] @type [$type] @max [$max] @vis [$v] diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 40c9ef3f63cf5..5ad50dca4adb6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -36,7 +36,7 @@ use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; use syntax::ptr::P; use syntax::ast::Expr; -use syntax::attr; +use syntax::attr::{self, HasAttrs}; use syntax::source_map::Spanned; use syntax::edition::Edition; use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType}; @@ -799,27 +799,81 @@ impl LintPass for UnusedDocComment { } impl UnusedDocComment { - fn warn_if_doc<'a, 'tcx, - I: Iterator, - C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) { - if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) { - cx.struct_span_lint(UNUSED_DOC_COMMENTS, attr.span, "doc comment not used by rustdoc") - .emit(); + fn warn_if_doc( + &self, + cx: &EarlyContext<'_>, + node_span: Span, + node_kind: &str, + is_macro_expansion: bool, + attrs: &[ast::Attribute] + ) { + let mut attrs = attrs.into_iter().peekable(); + + // Accumulate a single span for sugared doc comments. + let mut sugared_span: Option = None; + + while let Some(attr) = attrs.next() { + if attr.is_sugared_doc { + sugared_span = Some( + sugared_span.map_or_else( + || attr.span, + |span| span.with_hi(attr.span.hi()), + ), + ); + } + + if attrs.peek().map(|next_attr| next_attr.is_sugared_doc).unwrap_or_default() { + continue; + } + + let span = sugared_span.take().unwrap_or_else(|| attr.span); + + if attr.name() == "doc" { + let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment"); + + err.span_label( + node_span, + format!("rustdoc does not generate documentation for {}", node_kind) + ); + + if is_macro_expansion { + err.help("to document an item produced by a macro, \ + the macro must produce the documentation as part of its expansion"); + } + + err.emit(); + } } } } impl EarlyLintPass for UnusedDocComment { - fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) { - self.warn_if_doc(decl.attrs.iter(), cx); + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + if let ast::ItemKind::Mac(..) = item.node { + self.warn_if_doc(cx, item.span, "macro expansions", true, &item.attrs); + } + } + + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { + let (kind, is_macro_expansion) = match stmt.node { + ast::StmtKind::Local(..) => ("statements", false), + ast::StmtKind::Item(..) => ("inner items", false), + ast::StmtKind::Mac(..) => ("macro expansions", true), + // expressions will be reported by `check_expr`. + ast::StmtKind::Semi(..) | + ast::StmtKind::Expr(..) => return, + }; + + self.warn_if_doc(cx, stmt.span, kind, is_macro_expansion, stmt.node.attrs()); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - self.warn_if_doc(arm.attrs.iter(), cx); + let arm_span = arm.pats[0].span.with_hi(arm.body.span.hi()); + self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs); } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - self.warn_if_doc(expr.attrs.iter(), cx); + self.warn_if_doc(cx, expr.span, "expressions", false, &expr.attrs); } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 5c243e1389073..5e375dcaa0681 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -66,6 +66,7 @@ macro_rules! pre_expansion_lint_passes { ($macro:path, $args:tt) => ( $macro!($args, [ KeywordIdents: KeywordIdents, + UnusedDocComment: UnusedDocComment, ]); ) } @@ -77,7 +78,6 @@ macro_rules! early_lint_passes { UnusedImportBraces: UnusedImportBraces, UnsafeCode: UnsafeCode, AnonymousParameters: AnonymousParameters, - UnusedDocComment: UnusedDocComment, EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns, NonCamelCaseTypes: NonCamelCaseTypes, DeprecatedAttr: DeprecatedAttr::new(), diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index ef27fdbde387f..49b83315ce6e6 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -116,14 +116,14 @@ impl RegionValueElements { } } -/// A single integer representing a `Location` in the MIR control-flow -/// graph. Constructed efficiently from `RegionValueElements`. newtype_index! { + /// A single integer representing a `Location` in the MIR control-flow + /// graph. Constructed efficiently from `RegionValueElements`. pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" } } -/// A single integer representing a `ty::Placeholder`. newtype_index! { + /// A single integer representing a `ty::Placeholder`. pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs index b9f9d83161b79..fe60f8471629f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs @@ -85,10 +85,10 @@ impl NllLivenessMap { } } -/// Index given to each local variable for which we need to -/// compute liveness information. For many locals, we are able to -/// skip liveness information: for example, those variables whose -/// types contain no regions. newtype_index! { + /// Index given to each local variable for which we need to + /// compute liveness information. For many locals, we are able to + /// skip liveness information: for example, those variables whose + /// types contain no regions. pub struct LiveVar { .. } } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index efd979a7da4fb..07b93161e7218 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -23,7 +23,7 @@ pub(crate) mod indexes { use rustc_data_structures::indexed_vec::Idx; macro_rules! new_index { - ($Index:ident, $debug_name:expr) => { + ($(#[$attrs:meta])* $Index:ident, $debug_name:expr) => { #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct $Index(NonZeroUsize); @@ -44,17 +44,29 @@ pub(crate) mod indexes { } } - /// Index into MovePathData.move_paths - new_index!(MovePathIndex, "mp"); - - /// Index into MoveData.moves. - new_index!(MoveOutIndex, "mo"); - - /// Index into MoveData.inits. - new_index!(InitIndex, "in"); - - /// Index into Borrows.locations - new_index!(BorrowIndex, "bw"); + new_index!( + /// Index into MovePathData.move_paths + MovePathIndex, + "mp" + ); + + new_index!( + /// Index into MoveData.moves. + MoveOutIndex, + "mo" + ); + + new_index!( + /// Index into MoveData.inits. + InitIndex, + "in" + ); + + new_index!( + /// Index into Borrows.locations + BorrowIndex, + "bw" + ); } pub use self::indexes::MovePathIndex; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index e5caf7fdfa235..b1c53ea92b300 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -214,7 +214,7 @@ impl Options { if matches.opt_strs("passes") == ["list"] { println!("Available passes for running rustdoc:"); for pass in passes::PASSES { - println!("{:>20} - {}", pass.name(), pass.description()); + println!("{:>20} - {}", pass.name, pass.description); } println!("\nDefault passes for rustdoc:"); for &name in passes::DEFAULT_PASSES { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4f70751c90537..bf95cde163fc3 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -606,10 +606,12 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt passes::defaults(default_passes).iter().map(|p| p.to_string()).collect(); passes.extend(manual_passes); + info!("Executing passes"); + for pass in &passes { - // the "unknown pass" error will be reported when late passes are run - if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) { - krate = pass(krate, &ctxt); + match passes::find_pass(pass).map(|p| p.pass) { + Some(pass) => krate = pass(krate, &ctxt), + None => error!("unknown pass {}, skipping", *pass), } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 5e9f9ee9f80af..39e504951d1c6 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -441,28 +441,6 @@ where R: 'static + Send, krate.version = crate_version; - info!("Executing passes"); - - for pass in &passes { - // determine if we know about this pass - let pass = match passes::find_pass(pass) { - Some(pass) => if let Some(pass) = pass.late_fn() { - pass - } else { - // not a late pass, but still valid so don't report the error - continue - } - None => { - error!("unknown pass {}, skipping", *pass); - - continue - }, - }; - - // run it - krate = pass(krate); - } - tx.send(f(Output { krate: krate, renderinfo: renderinfo, diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index f960374370e04..88d9c87c52898 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -10,9 +10,11 @@ use crate::fold::DocFolder; use crate::html::markdown::{self, RustCodeBlock}; use crate::passes::Pass; -pub const CHECK_CODE_BLOCK_SYNTAX: Pass = - Pass::early("check-code-block-syntax", check_code_block_syntax, - "validates syntax inside Rust code blocks"); +pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { + name: "check-code-block-syntax", + pass: check_code_block_syntax, + description: "validates syntax inside Rust code blocks", +}; pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext<'_, '_, '_>) -> clean::Crate { SyntaxChecker { cx }.fold_crate(krate) diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index e5e60cbe71700..088a6ea77c73f 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -1,13 +1,16 @@ use crate::clean::{self, DocFragment, Item}; +use crate::core::DocContext; use crate::fold; use crate::fold::{DocFolder}; use crate::passes::Pass; use std::mem::replace; -pub const COLLAPSE_DOCS: Pass = - Pass::late("collapse-docs", collapse_docs, - "concatenates all document attributes into one document attribute"); +pub const COLLAPSE_DOCS: Pass = Pass { + name: "collapse-docs", + pass: collapse_docs, + description: "concatenates all document attributes into one document attribute", +}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum DocFragmentKind { @@ -26,7 +29,7 @@ impl DocFragment { } } -pub fn collapse_docs(krate: clean::Crate) -> clean::Crate { +pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate { Collapser.fold_crate(krate) } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 42fa3e2006b42..67f291285c447 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -19,9 +19,11 @@ use crate::passes::{look_for_tests, Pass}; use super::span_of_attrs; -pub const COLLECT_INTRA_DOC_LINKS: Pass = - Pass::early("collect-intra-doc-links", collect_intra_doc_links, - "reads a crate's documentation to resolve intra-doc-links"); +pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass { + name: "collect-intra-doc-links", + pass: collect_intra_doc_links, + description: "reads a crate's documentation to resolve intra-doc-links", +}; pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate { if !UnstableFeatures::from_environment().is_nightly_build() { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 903cce3bc032a..4c90540871d2e 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -6,9 +6,11 @@ use super::Pass; use rustc::util::nodemap::FxHashSet; use rustc::hir::def_id::DefId; -pub const COLLECT_TRAIT_IMPLS: Pass = - Pass::early("collect-trait-impls", collect_trait_impls, - "retrieves trait impls for items in the crate"); +pub const COLLECT_TRAIT_IMPLS: Pass = Pass { + name: "collect-trait-impls", + pass: collect_trait_impls, + description: "retrieves trait impls for items in the crate", +}; pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate { let mut synth = SyntheticImplCollector::new(cx); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 4d7fef7a76a9f..3a9d8ef20ce84 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -6,7 +6,6 @@ use rustc::lint as lint; use rustc::middle::privacy::AccessLevels; use rustc::util::nodemap::DefIdSet; use std::mem; -use std::fmt; use syntax::ast::NodeId; use syntax_pos::{DUMMY_SP, Span}; use std::ops::Range; @@ -46,84 +45,14 @@ pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; mod check_code_block_syntax; pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX; -/// Represents a single pass. +/// A single pass over the cleaned documentation. +/// +/// Runs in the compiler context, so it has access to types and traits and the like. #[derive(Copy, Clone)] -pub enum Pass { - /// An "early pass" is run in the compiler context, and can gather information about types and - /// traits and the like. - EarlyPass { - name: &'static str, - pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate, - description: &'static str, - }, - /// A "late pass" is run between crate cleaning and page generation. - LatePass { - name: &'static str, - pass: fn(clean::Crate) -> clean::Crate, - description: &'static str, - }, -} - -impl fmt::Debug for Pass { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut dbg = match *self { - Pass::EarlyPass { .. } => f.debug_struct("EarlyPass"), - Pass::LatePass { .. } => f.debug_struct("LatePass"), - }; - - dbg.field("name", &self.name()) - .field("pass", &"...") - .field("description", &self.description()) - .finish() - } -} - -impl Pass { - /// Constructs a new early pass. - pub const fn early(name: &'static str, - pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate, - description: &'static str) -> Pass { - Pass::EarlyPass { name, pass, description } - } - - /// Constructs a new late pass. - pub const fn late(name: &'static str, - pass: fn(clean::Crate) -> clean::Crate, - description: &'static str) -> Pass { - Pass::LatePass { name, pass, description } - } - - /// Returns the name of this pass. - pub fn name(self) -> &'static str { - match self { - Pass::EarlyPass { name, .. } | - Pass::LatePass { name, .. } => name, - } - } - - /// Returns the description of this pass. - pub fn description(self) -> &'static str { - match self { - Pass::EarlyPass { description, .. } | - Pass::LatePass { description, .. } => description, - } - } - - /// If this pass is an early pass, returns the pointer to its function. - pub fn early_fn(self) -> Option) -> clean::Crate> { - match self { - Pass::EarlyPass { pass, .. } => Some(pass), - _ => None, - } - } - - /// If this pass is a late pass, returns the pointer to its function. - pub fn late_fn(self) -> Option clean::Crate> { - match self { - Pass::LatePass { pass, .. } => Some(pass), - _ => None, - } - } +pub struct Pass { + pub name: &'static str, + pub pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate, + pub description: &'static str, } /// The full list of passes. @@ -141,27 +70,27 @@ pub const PASSES: &'static [Pass] = &[ ]; /// The list of passes run by default. -pub const DEFAULT_PASSES: &'static [&'static str] = &[ +pub const DEFAULT_PASSES: &[&str] = &[ "collect-trait-impls", + "collapse-docs", + "unindent-comments", "check-private-items-doc-tests", "strip-hidden", "strip-private", "collect-intra-doc-links", "check-code-block-syntax", - "collapse-docs", - "unindent-comments", "propagate-doc-cfg", ]; /// The list of default passes run with `--document-private-items` is passed to rustdoc. -pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[ +pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[ "collect-trait-impls", + "collapse-docs", + "unindent-comments", "check-private-items-doc-tests", "strip-priv-imports", "collect-intra-doc-links", "check-code-block-syntax", - "collapse-docs", - "unindent-comments", "propagate-doc-cfg", ]; @@ -184,8 +113,8 @@ pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] { } /// If the given name matches a known pass, returns its information. -pub fn find_pass(pass_name: &str) -> Option { - PASSES.iter().find(|p| p.name() == pass_name).cloned() +pub fn find_pass(pass_name: &str) -> Option<&'static Pass> { + PASSES.iter().find(|p| p.name == pass_name) } struct Stripper<'a> { @@ -438,11 +367,11 @@ crate fn source_span_for_markdown_range( .span_to_snippet(span_of_attrs(attrs)) .ok()?; - let starting_line = markdown[..md_range.start].lines().count() - 1; - let ending_line = markdown[..md_range.end].lines().count() - 1; + let starting_line = markdown[..md_range.start].matches('\n').count(); + let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count(); - // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only - // we can treat CRLF and LF line endings the same way. + // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we treat + // CRLF and LF line endings the same way. let mut src_lines = snippet.split_terminator('\n'); let md_lines = markdown.split_terminator('\n'); diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs index 819d15f65e8ef..1c3977c4f85cd 100644 --- a/src/librustdoc/passes/private_items_doc_tests.rs +++ b/src/librustdoc/passes/private_items_doc_tests.rs @@ -3,10 +3,11 @@ use crate::core::DocContext; use crate::fold::DocFolder; use crate::passes::{look_for_tests, Pass}; - -pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = - Pass::early("check-private-items-doc-tests", check_private_items_doc_tests, - "check private items doc tests"); +pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass { + name: "check-private-items-doc-tests", + pass: check_private_items_doc_tests, + description: "check private items doc tests", +}; struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a> { cx: &'a DocContext<'a, 'tcx, 'rcx>, diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 9ba0b22728691..aed80b5ba86fd 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -2,14 +2,17 @@ use std::sync::Arc; use crate::clean::{Crate, Item}; use crate::clean::cfg::Cfg; +use crate::core::DocContext; use crate::fold::DocFolder; use crate::passes::Pass; -pub const PROPAGATE_DOC_CFG: Pass = - Pass::late("propagate-doc-cfg", propagate_doc_cfg, - "propagates `#[doc(cfg(...))]` to child items"); +pub const PROPAGATE_DOC_CFG: Pass = Pass { + name: "propagate-doc-cfg", + pass: propagate_doc_cfg, + description: "propagates `#[doc(cfg(...))]` to child items", +}; -pub fn propagate_doc_cfg(cr: Crate) -> Crate { +pub fn propagate_doc_cfg(cr: Crate, _: &DocContext<'_, '_, '_>) -> Crate { CfgPropagator { parent_cfg: None }.fold_crate(cr) } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index b3d50e06816c5..330057e53843b 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -7,9 +7,11 @@ use crate::core::DocContext; use crate::fold::{DocFolder, StripItem}; use crate::passes::{ImplStripper, Pass}; -pub const STRIP_HIDDEN: Pass = - Pass::early("strip-hidden", strip_hidden, - "strips all doc(hidden) items from the output"); +pub const STRIP_HIDDEN: Pass = Pass { + name: "strip-hidden", + pass: strip_hidden, + description: "strips all doc(hidden) items from the output", +}; /// Strip items marked `#[doc(hidden)]` pub fn strip_hidden(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate { diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index 3af1403e8749c..479f0877bd7d2 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -3,8 +3,11 @@ use crate::fold::{DocFolder}; use crate::core::DocContext; use crate::passes::{ImportStripper, Pass}; -pub const STRIP_PRIV_IMPORTS: Pass = Pass::early("strip-priv-imports", strip_priv_imports, - "strips all private import statements (`use`, `extern crate`) from a crate"); +pub const STRIP_PRIV_IMPORTS: Pass = Pass { + name: "strip-priv-imports", + pass: strip_priv_imports, + description: "strips all private import statements (`use`, `extern crate`) from a crate", +}; pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate { ImportStripper.fold_crate(krate) diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index e553d792eb697..1ac3a90f38d35 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -5,10 +5,12 @@ use crate::fold::{DocFolder}; use crate::core::DocContext; use crate::passes::{ImplStripper, ImportStripper, Stripper, Pass}; -pub const STRIP_PRIVATE: Pass = - Pass::early("strip-private", strip_private, - "strips all private items from a crate which cannot be seen externally, \ - implies strip-priv-imports"); +pub const STRIP_PRIVATE: Pass = Pass { + name: "strip-private", + pass: strip_private, + description: "strips all private items from a crate which cannot be seen externally, \ + implies strip-priv-imports", +}; /// Strip private items from the point of view of a crate or externally from a /// crate, specified by the `xcrate` flag. diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 269e4cbe65f8b..b77cf68d7c63f 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -3,14 +3,17 @@ use std::string::String; use std::usize; use crate::clean::{self, DocFragment, Item}; +use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::passes::Pass; -pub const UNINDENT_COMMENTS: Pass = - Pass::late("unindent-comments", unindent_comments, - "removes excess indentation on comments in order for markdown to like it"); +pub const UNINDENT_COMMENTS: Pass = Pass { + name: "unindent-comments", + pass: unindent_comments, + description: "removes excess indentation on comments in order for markdown to like it", +}; -pub fn unindent_comments(krate: clean::Crate) -> clean::Crate { +pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate { CommentCleaner.fold_crate(krate) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b634ea43e34e5..b49eea391772a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1458,7 +1458,7 @@ pub trait BufRead: Read { /// /// If successful, this function will return the total number of bytes read. /// - /// An empty buffer returned indicates that the stream has reached EOF. + /// If this function returns `Ok(0)`, the stream has reached EOF. /// /// # Errors /// diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 0324568e6fb52..00bd8e5e4de18 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -9,8 +9,8 @@ use sys::stdio; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use thread::LocalKey; -/// Stdout used by print! and println! macros thread_local! { + /// Stdout used by print! and println! macros static LOCAL_STDOUT: RefCell>> = { RefCell::new(None) } diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs new file mode 100644 index 0000000000000..43ce21908a958 --- /dev/null +++ b/src/test/debuginfo/empty-string.rs @@ -0,0 +1,33 @@ +// compile-flags:-g +// min-gdb-version: 7.7 +// min-lldb-version: 310 + +// === GDB TESTS =================================================================================== + +// gdb-command: run + +// gdb-command: print empty_string +// gdb-check:$1 = "" + +// gdb-command: print empty_str +// gdb-check:$2 = "" + +// === LLDB TESTS ================================================================================== + +// lldb-command: run + +// lldb-command: fr v empty_string +// lldb-check:[...]empty_string = "" + +// lldb-command: fr v empty_str +// lldb-check:[...]empty_str = "" + +fn main() { + let empty_string = String::new(); + + let empty_str = ""; + + zzz(); // #break +} + +fn zzz() {} diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index e5409c042056c..60fc131dbda17 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -105,8 +105,8 @@ LL | | /// [error] | = note: the link appears in this line: - [error] - ^^^^^ + [error] + ^^^^^ = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` warning: `[error1]` cannot be resolved, ignoring it... diff --git a/src/test/rustdoc-ui/issue-58473-2.rs b/src/test/rustdoc-ui/issue-58473-2.rs new file mode 100644 index 0000000000000..5e5ddebe10884 --- /dev/null +++ b/src/test/rustdoc-ui/issue-58473-2.rs @@ -0,0 +1,12 @@ +// compile-pass + +#![deny(private_doc_tests)] + +mod foo { + /** + Does nothing, returns `()` + + yadda-yadda-yadda + */ + fn foo() {} +} diff --git a/src/test/rustdoc-ui/issue-58473.rs b/src/test/rustdoc-ui/issue-58473.rs new file mode 100644 index 0000000000000..0e5be3292c053 --- /dev/null +++ b/src/test/rustdoc-ui/issue-58473.rs @@ -0,0 +1,10 @@ +// compile-pass + +pub trait Foo { + /** + Does nothing, returns `()` + + yadda-yadda-yadda + */ + fn foo() {} +} diff --git a/src/test/ui/useless_comment.rs b/src/test/ui/useless_comment.rs index 531eec007fc48..7d2e5ab6f2b7f 100644 --- a/src/test/ui/useless_comment.rs +++ b/src/test/ui/useless_comment.rs @@ -1,18 +1,43 @@ +#![feature(stmt_expr_attributes)] + #![deny(unused_doc_comments)] +macro_rules! mac { + () => {} +} + +/// foo //~ ERROR unused doc comment +mac!(); + fn foo() { - /// a //~ ERROR doc comment not used by rustdoc + /// a //~ ERROR unused doc comment let x = 12; - /// b //~ doc comment not used by rustdoc + /// multi-line //~ unused doc comment + /// doc comment + /// that is unused match x { - /// c //~ ERROR doc comment not used by rustdoc + /// c //~ ERROR unused doc comment 1 => {}, _ => {} } - /// foo //~ ERROR doc comment not used by rustdoc + /// foo //~ ERROR unused doc comment unsafe {} + + #[doc = "foo"] //~ ERROR unused doc comment + #[doc = "bar"] //~ ERROR unused doc comment + 3; + + /// bar //~ ERROR unused doc comment + mac!(); + + let x = /** comment */ 47; //~ ERROR unused doc comment + + /// dox //~ ERROR unused doc comment + { + + } } fn main() { diff --git a/src/test/ui/useless_comment.stderr b/src/test/ui/useless_comment.stderr index cc818f6ce7c39..0742a844b7f40 100644 --- a/src/test/ui/useless_comment.stderr +++ b/src/test/ui/useless_comment.stderr @@ -1,32 +1,98 @@ -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:4:5 +error: unused doc comment + --> $DIR/useless_comment.rs:9:1 | -LL | /// a //~ ERROR doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | /// foo //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | mac!(); + | ------- rustdoc does not generate documentation for macro expansions | note: lint level defined here - --> $DIR/useless_comment.rs:1:9 + --> $DIR/useless_comment.rs:3:9 | LL | #![deny(unused_doc_comments)] | ^^^^^^^^^^^^^^^^^^^ + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:7:5 +error: unused doc comment + --> $DIR/useless_comment.rs:13:5 | -LL | /// b //~ doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | /// a //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:9:9 +error: unused doc comment + --> $DIR/useless_comment.rs:16:5 | -LL | /// c //~ ERROR doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / /// multi-line //~ unused doc comment +LL | | /// doc comment +LL | | /// that is unused + | |______________________^ +LL | / match x { +LL | | /// c //~ ERROR unused doc comment +LL | | 1 => {}, +LL | | _ => {} +LL | | } + | |_____- rustdoc does not generate documentation for expressions -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:14:5 +error: unused doc comment + --> $DIR/useless_comment.rs:20:9 | -LL | /// foo //~ ERROR doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | /// c //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 1 => {}, + | ------- rustdoc does not generate documentation for match arms -error: aborting due to 4 previous errors +error: unused doc comment + --> $DIR/useless_comment.rs:25:5 + | +LL | /// foo //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe {} + | --------- rustdoc does not generate documentation for expressions + +error: unused doc comment + --> $DIR/useless_comment.rs:28:5 + | +LL | #[doc = "foo"] //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^ +LL | #[doc = "bar"] //~ ERROR unused doc comment +LL | 3; + | - rustdoc does not generate documentation for expressions + +error: unused doc comment + --> $DIR/useless_comment.rs:29:5 + | +LL | #[doc = "bar"] //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^ +LL | 3; + | - rustdoc does not generate documentation for expressions + +error: unused doc comment + --> $DIR/useless_comment.rs:32:5 + | +LL | /// bar //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | mac!(); + | ------- rustdoc does not generate documentation for macro expansions + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: unused doc comment + --> $DIR/useless_comment.rs:35:13 + | +LL | let x = /** comment */ 47; //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions + +error: unused doc comment + --> $DIR/useless_comment.rs:37:5 + | +LL | /// dox //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | +LL | | } + | |_____- rustdoc does not generate documentation for expressions + +error: aborting due to 10 previous errors