From d3394685be76dd0853d4bb0d0cfea10f31b4a9db Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 23 Jan 2019 13:44:43 -0500 Subject: [PATCH 01/38] improve unused doc comment diagnostic reporting Report all unused attributes on a given doc comment instead of just the first one, and extend the span of sugared doc comments to encompass the whole comment. --- src/librustc_lint/builtin.rs | 41 +++++++++++++++++++++++------- src/test/ui/useless_comment.rs | 8 +++++- src/test/ui/useless_comment.stderr | 24 +++++++++++++---- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 925cde5b5cc8b..ef7be4d0b1848 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -799,27 +799,50 @@ 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<'_>, 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" { + cx.struct_span_lint( + UNUSED_DOC_COMMENTS, + span, + "doc comment not used by rustdoc", + ).emit(); + } } } } impl EarlyLintPass for UnusedDocComment { fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) { - self.warn_if_doc(decl.attrs.iter(), cx); + self.warn_if_doc(cx, &decl.attrs); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - self.warn_if_doc(arm.attrs.iter(), cx); + self.warn_if_doc(cx, &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.attrs); } } diff --git a/src/test/ui/useless_comment.rs b/src/test/ui/useless_comment.rs index 531eec007fc48..e8a0e3c10d222 100644 --- a/src/test/ui/useless_comment.rs +++ b/src/test/ui/useless_comment.rs @@ -4,7 +4,9 @@ fn foo() { /// a //~ ERROR doc comment not used by rustdoc let x = 12; - /// b //~ doc comment not used by rustdoc + /// multi-line //~ doc comment not used by rustdoc + /// doc comment + /// that is unused match x { /// c //~ ERROR doc comment not used by rustdoc 1 => {}, @@ -13,6 +15,10 @@ fn foo() { /// foo //~ ERROR doc comment not used by rustdoc unsafe {} + + #[doc = "foo"] //~ ERROR doc comment not used by rustdoc + #[doc = "bar"] //~ ERROR doc comment not used by rustdoc + 3; } fn main() { diff --git a/src/test/ui/useless_comment.stderr b/src/test/ui/useless_comment.stderr index cc818f6ce7c39..a284c08f47ace 100644 --- a/src/test/ui/useless_comment.stderr +++ b/src/test/ui/useless_comment.stderr @@ -13,20 +13,34 @@ LL | #![deny(unused_doc_comments)] error: doc comment not used by rustdoc --> $DIR/useless_comment.rs:7:5 | -LL | /// b //~ doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / /// multi-line //~ doc comment not used by rustdoc +LL | | /// doc comment +LL | | /// that is unused + | |______________________^ error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:9:9 + --> $DIR/useless_comment.rs:11:9 | LL | /// c //~ ERROR doc comment not used by rustdoc | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:14:5 + --> $DIR/useless_comment.rs:16:5 | LL | /// foo //~ ERROR doc comment not used by rustdoc | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: doc comment not used by rustdoc + --> $DIR/useless_comment.rs:19:5 + | +LL | #[doc = "foo"] //~ ERROR doc comment not used by rustdoc + | ^^^^^^^^^^^^^^ + +error: doc comment not used by rustdoc + --> $DIR/useless_comment.rs:20:5 + | +LL | #[doc = "bar"] //~ ERROR doc comment not used by rustdoc + | ^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors From b5fadf044ca96b602239633b929f2d14388c6b8c Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 24 Jan 2019 15:49:03 -0500 Subject: [PATCH 02/38] expand unused doc comment diagnostic Report the diagnostic on macro expansions, and add a label indicating why the comment is unused. --- src/libcore/num/mod.rs | 2 +- src/librustc/hir/mod.rs | 16 +-- src/librustc/middle/region.rs | 35 ++++--- src/librustc/ty/context.rs | 19 ++-- src/librustc/ty/mod.rs | 70 ++++++------- src/librustc/ty/sty.rs | 78 +++++++-------- src/librustc_data_structures/indexed_vec.rs | 30 +++++- src/librustc_lint/builtin.rs | 53 +++++++--- src/librustc_lint/lib.rs | 2 +- .../borrow_check/nll/region_infer/values.rs | 6 +- .../nll/type_check/liveness/liveness_map.rs | 8 +- src/librustc_mir/dataflow/move_paths/mod.rs | 36 ++++--- src/libstd/io/stdio.rs | 2 +- src/test/ui/useless_comment.rs | 31 ++++-- src/test/ui/useless_comment.stderr | 98 ++++++++++++++----- 15 files changed, 313 insertions(+), 173 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6fb67ea9c9acb..1eda784d66be1 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4617,7 +4617,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 d7d56ef659afb..e9a4b19f7653d 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 66efd2aea155a..8015b8ac09c4b 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 ef7be4d0b1848..531ec83e6c7d5 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,7 +799,14 @@ impl LintPass for UnusedDocComment { } impl UnusedDocComment { - fn warn_if_doc(&self, cx: &EarlyContext<'_>, attrs: &[ast::Attribute]) { + 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. @@ -822,27 +829,51 @@ impl UnusedDocComment { let span = sugared_span.take().unwrap_or_else(|| attr.span); if attr.name() == "doc" { - cx.struct_span_lint( - UNUSED_DOC_COMMENTS, - span, - "doc comment not used by rustdoc", - ).emit(); + 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(cx, &decl.attrs); + 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(cx, &arm.attrs); + 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(cx, &expr.attrs); + 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/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 4068c0f9c7de5..2ffaf4d8899ba 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/ui/useless_comment.rs b/src/test/ui/useless_comment.rs index e8a0e3c10d222..7d2e5ab6f2b7f 100644 --- a/src/test/ui/useless_comment.rs +++ b/src/test/ui/useless_comment.rs @@ -1,24 +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; - /// multi-line //~ 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 doc comment not used by rustdoc - #[doc = "bar"] //~ ERROR doc comment not used by rustdoc + #[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 a284c08f47ace..0742a844b7f40 100644 --- a/src/test/ui/useless_comment.stderr +++ b/src/test/ui/useless_comment.stderr @@ -1,46 +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 | / /// multi-line //~ doc comment not used by rustdoc +LL | /// a //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements + +error: unused doc comment + --> $DIR/useless_comment.rs:16:5 + | +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:11:9 +error: unused doc comment + --> $DIR/useless_comment.rs:20:9 | -LL | /// c //~ ERROR doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | /// c //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 1 => {}, + | ------- rustdoc does not generate documentation for match arms -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:16:5 +error: unused doc comment + --> $DIR/useless_comment.rs:25:5 | -LL | /// foo //~ ERROR doc comment not used by rustdoc - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | /// foo //~ ERROR unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe {} + | --------- rustdoc does not generate documentation for expressions -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:19:5 +error: unused doc comment + --> $DIR/useless_comment.rs:28:5 | -LL | #[doc = "foo"] //~ ERROR doc comment not used by rustdoc +LL | #[doc = "foo"] //~ ERROR unused doc comment | ^^^^^^^^^^^^^^ +LL | #[doc = "bar"] //~ ERROR unused doc comment +LL | 3; + | - rustdoc does not generate documentation for expressions -error: doc comment not used by rustdoc - --> $DIR/useless_comment.rs:20:5 +error: unused doc comment + --> $DIR/useless_comment.rs:29:5 | -LL | #[doc = "bar"] //~ ERROR doc comment not used by rustdoc +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 6 previous errors +error: aborting due to 10 previous errors From 890ef48eb93c42e8a6c5535a6aefa02291b93b2d Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 23 Feb 2019 18:57:25 +0000 Subject: [PATCH 03/38] Fix an indexing error when using `x.py help` --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 906ec8acce8126172df758e7e7f400429c3489dc Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 20 Feb 2019 16:20:01 -0500 Subject: [PATCH 04/38] move collapse and unindent docs passes earlier --- src/librustdoc/passes/collapse_docs.rs | 5 +++-- src/librustdoc/passes/mod.rs | 20 +++++++++---------- src/librustdoc/passes/unindent_comments.rs | 5 +++-- .../rustdoc-ui/intra-links-warning.stderr | 4 ++-- src/test/rustdoc-ui/issue-58473-2.rs | 12 +++++++++++ src/test/rustdoc-ui/issue-58473.rs | 10 ++++++++++ 6 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 src/test/rustdoc-ui/issue-58473-2.rs create mode 100644 src/test/rustdoc-ui/issue-58473.rs diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index e5e60cbe71700..399f8261d21ec 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -1,4 +1,5 @@ use crate::clean::{self, DocFragment, Item}; +use crate::core::DocContext; use crate::fold; use crate::fold::{DocFolder}; use crate::passes::Pass; @@ -6,7 +7,7 @@ use crate::passes::Pass; use std::mem::replace; pub const COLLAPSE_DOCS: Pass = - Pass::late("collapse-docs", collapse_docs, + Pass::early("collapse-docs", collapse_docs, "concatenates all document attributes into one document attribute"); #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -26,7 +27,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/mod.rs b/src/librustdoc/passes/mod.rs index 4d7fef7a76a9f..db2bb89843848 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -141,27 +141,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", ]; @@ -438,11 +438,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/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index 269e4cbe65f8b..c32c3556a5728 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -3,14 +3,15 @@ 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, + Pass::early("unindent-comments", unindent_comments, "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/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() {} +} From 1536852b428b56a13a3026354db72e0b83c83652 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sat, 23 Feb 2019 15:10:56 -0500 Subject: [PATCH 05/38] merge early and late passes into single struct --- src/librustdoc/config.rs | 2 +- src/librustdoc/core.rs | 8 +- src/librustdoc/lib.rs | 22 ----- .../passes/check_code_block_syntax.rs | 8 +- src/librustdoc/passes/collapse_docs.rs | 8 +- .../passes/collect_intra_doc_links.rs | 8 +- src/librustdoc/passes/collect_trait_impls.rs | 8 +- src/librustdoc/passes/mod.rs | 89 ++----------------- .../passes/private_items_doc_tests.rs | 9 +- src/librustdoc/passes/propagate_doc_cfg.rs | 11 ++- src/librustdoc/passes/strip_hidden.rs | 8 +- src/librustdoc/passes/strip_priv_imports.rs | 7 +- src/librustdoc/passes/strip_private.rs | 10 ++- src/librustdoc/passes/unindent_comments.rs | 8 +- 14 files changed, 68 insertions(+), 138 deletions(-) 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 399f8261d21ec..088a6ea77c73f 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -6,9 +6,11 @@ use crate::passes::Pass; use std::mem::replace; -pub const COLLAPSE_DOCS: Pass = - Pass::early("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 { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index cf2c3aa484600..532bb96445105 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -18,9 +18,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 db2bb89843848..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. @@ -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> { 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 c32c3556a5728..b77cf68d7c63f 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -7,9 +7,11 @@ use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::passes::Pass; -pub const UNINDENT_COMMENTS: Pass = - Pass::early("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, _: &DocContext<'_, '_, '_>) -> clean::Crate { CommentCleaner.fold_crate(krate) From 8300f51936149ec43eb063205e4d03c54a308f3c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Sat, 23 Feb 2019 18:39:27 +0000 Subject: [PATCH 06/38] Deny `async fn` in 2015 edition Fix style issues and update diagnostic messages Update src/librustc_passes/diagnostics.rs Co-Authored-By: doctorn Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition Deny nested `async fn` in Rust 2015 edition --- src/librustc/hir/lowering.rs | 10 ++-- src/librustc/hir/map/def_collector.rs | 10 ++-- src/librustc_passes/ast_validation.rs | 14 ++++- src/librustc_passes/diagnostics.rs | 12 ++++ src/librustc_resolve/lib.rs | 4 +- src/librustc_save_analysis/sig.rs | 4 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/parse/parser.rs | 39 +++++++++---- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax/visit.rs | 15 +++-- src/libsyntax_ext/test.rs | 2 +- .../editions/edition-deny-async-fns-2015.rs | 34 +++++++++++ .../edition-deny-async-fns-2015.stderr | 58 +++++++++++++++++++ .../feature-gate-async-await-2015-edition.rs | 3 +- ...ature-gate-async-await-2015-edition.stderr | 16 +++-- .../recursive-async-impl-trait-type.rs | 11 ++++ .../recursive-async-impl-trait-type.stderr | 11 ++++ .../impl-trait/recursive-impl-trait-type.rs | 6 +- .../recursive-impl-trait-type.stderr | 14 +---- 22 files changed, 215 insertions(+), 62 deletions(-) create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.rs create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.stderr create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f6b68682886e7..f65bd255ba66e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2906,7 +2906,7 @@ impl<'a> LoweringContext<'a> { // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_async_body(decl, header.asyncness, body); + let body_id = this.lower_async_body(decl, header.asyncness.node, body); let (generics, fn_decl) = this.add_in_band_defs( generics, @@ -2916,7 +2916,7 @@ impl<'a> LoweringContext<'a> { decl, Some((fn_def_id, idty)), true, - header.asyncness.opt_return_id() + header.asyncness.node.opt_return_id() ), ); @@ -3410,14 +3410,14 @@ impl<'a> LoweringContext<'a> { ) } ImplItemKind::Method(ref sig, ref body) => { - let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body); + let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( &i.generics, sig, impl_item_def_id, impl_trait_return_allow, - sig.header.asyncness.opt_return_id(), + sig.header.asyncness.node.opt_return_id(), ); (generics, hir::ImplItemKind::Method(sig, body_id)) } @@ -3637,7 +3637,7 @@ impl<'a> LoweringContext<'a> { fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { hir::FnHeader { unsafety: self.lower_unsafety(h.unsafety), - asyncness: self.lower_asyncness(h.asyncness), + asyncness: self.lower_asyncness(h.asyncness.node), constness: self.lower_constness(h.constness), abi: h.abi, } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 72aa9570cc2ff..12760f8b9828b 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -73,7 +73,7 @@ impl<'a> DefCollector<'a> { decl: &'a FnDecl, body: &'a Block, ) { - let (closure_id, return_impl_trait_id) = match header.asyncness { + let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { closure_id, return_impl_trait_id, @@ -129,10 +129,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } ItemKind::Fn( ref decl, - ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref header, ref generics, ref body, - ) => { + ) if header.asyncness.node.is_async() => { return self.visit_async_fn( i.id, i.ident.name, @@ -242,9 +242,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(MethodSig { - header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref header, ref decl, - }, ref body) => { + }, ref body) if header.asyncness.node.is_async() => { return self.visit_async_fn( ii.id, ii.ident.name, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 606ae27412832..f96fc3b897f80 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -463,7 +463,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&impl_item.vis, None); if let ImplItemKind::Method(ref sig, _) = impl_item.node { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness); + self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } } } @@ -482,9 +482,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .note("only trait implementations may be annotated with default").emit(); } } - ItemKind::Fn(_, header, ref generics, _) => { + ItemKind::Fn(_, ref header, ref generics, _) => { // We currently do not permit const generics in `const fn`, as // this is tantamount to allowing compile-time dependent typing. + self.visit_fn_header(header); if header.constness.node == Constness::Const { // Look for const generics and error if we find any. for param in &generics.params { @@ -535,7 +536,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.no_questions_in_bounds(bounds, "supertraits", true); for trait_item in trait_items { if let TraitItemKind::Method(ref sig, ref block) = trait_item.node { - self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness); + self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { self.check_decl_no_pat(&sig.decl, |span, mut_ident| { @@ -702,6 +703,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \ the relevant `fold_*()` method in `PlaceholderExpander`?"); } + + fn visit_fn_header(&mut self, header: &'a FnHeader) { + if header.asyncness.node.is_async() && self.session.rust_2015() { + struct_span_err!(self.session, header.asyncness.span, E0670, + "`async fn` is not permitted in the 2015 edition").emit(); + } + } } pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) { diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 19d4d3aeb0f65..e3c6b16703a4a 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -310,6 +310,18 @@ loop { break; } ``` +"##, + +E0670: r##" +Rust 2015 does not permit the use of `async fn`. + +Example of erroneous code: + +```compile_fail,E0670 +async fn foo() {} +``` + +Switch to the Rust 2018 edition to use `async fn`. "## } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1a7744786d80e..3993964bd9db9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -806,9 +806,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { debug!("(resolving function) entering function"); let (rib_kind, asyncness) = match function_kind { FnKind::ItemFn(_, ref header, ..) => - (ItemRibKind, header.asyncness), + (ItemRibKind, header.asyncness.node), FnKind::Method(_, ref sig, _, _) => - (TraitOrImplItemRibKind, sig.header.asyncness), + (TraitOrImplItemRibKind, sig.header.asyncness.node), FnKind::Closure(_) => // Async closures aren't resolved through `visit_fn`-- they're // processed separately diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 50a335bf90877..52f3a20777021 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -378,7 +378,7 @@ impl Sig for ast::Item { if header.constness.node == ast::Constness::Const { text.push_str("const "); } - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { text.push_str("async "); } if header.unsafety == ast::Unsafety::Unsafe { @@ -936,7 +936,7 @@ fn make_method_signature( if m.header.constness.node == ast::Constness::Const { text.push_str("const "); } - if m.header.asyncness.is_async() { + if m.header.asyncness.node.is_async() { text.push_str("async "); } if m.header.unsafety == ast::Unsafety::Unsafe { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9c4945d74dbfe..b6f9ae36da70c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2216,7 +2216,7 @@ impl Item { #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafety, - pub asyncness: IsAsync, + pub asyncness: Spanned, pub constness: Spanned, pub abi: Abi, } @@ -2225,7 +2225,7 @@ impl Default for FnHeader { fn default() -> FnHeader { FnHeader { unsafety: Unsafety::Normal, - asyncness: IsAsync::NotAsync, + asyncness: dummy_spanned(IsAsync::NotAsync), constness: dummy_spanned(Constness::NotConst), abi: Abi::Rust, } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 27b0cfb163077..2f88749ace85e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1017,7 +1017,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)), ast::FnHeader { unsafety: ast::Unsafety::Normal, - asyncness: ast::IsAsync::NotAsync, + asyncness: dummy_spanned(ast::IsAsync::NotAsync), constness: dummy_spanned(ast::Constness::NotConst), abi: Abi::Rust, }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d574b410ccc06..0f7ba041f9c08 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1894,7 +1894,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match fn_kind { FnKind::ItemFn(_, header, _, _) => { // Check for const fn and async fn declarations. - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { gate_feature_post!(&self, async_await, span, "async fn is unstable"); } // Stability of const fn methods are covered in diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 86849f580d081..935142e8a2def 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -926,7 +926,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header; - vis.visit_asyncness(asyncness); + vis.visit_asyncness(&mut asyncness.node); } pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a753e1f8c8a5..c257f05ae468e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5001,6 +5001,11 @@ impl<'a> Parser<'a> { ) } + fn is_async_fn(&mut self) -> bool { + self.token.is_keyword(keywords::Async) && + self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) + } + fn is_do_catch_block(&mut self) -> bool { self.token.is_keyword(keywords::Do) && self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) && @@ -5133,7 +5138,8 @@ impl<'a> Parser<'a> { !self.is_union_item() && !self.is_crate_vis() && !self.is_existential_type_decl() && - !self.is_auto_trait_item() { + !self.is_auto_trait_item() && + !self.is_async_fn() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -6346,7 +6352,7 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn(&mut self, unsafety: Unsafety, - asyncness: IsAsync, + asyncness: Spanned, constness: Spanned, abi: Abi) -> PResult<'a, ItemInfo> { @@ -6378,7 +6384,7 @@ impl<'a> Parser<'a> { -> PResult<'a, ( Spanned, Unsafety, - IsAsync, + Spanned, Abi )> { @@ -6386,6 +6392,7 @@ impl<'a> Parser<'a> { let const_span = self.prev_span; let unsafety = self.parse_unsafety(); let asyncness = self.parse_asyncness(); + let asyncness = respan(self.prev_span, asyncness); let (constness, unsafety, abi) = if is_const_fn { (respan(const_span, Constness::Const), unsafety, Abi::Rust) } else { @@ -7796,7 +7803,7 @@ impl<'a> Parser<'a> { let abi = opt_abi.unwrap_or(Abi::C); let (ident, item_, extra_attrs) = self.parse_item_fn(Unsafety::Normal, - IsAsync::NotAsync, + respan(fn_span, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), abi)?; let prev_span = self.prev_span; @@ -7840,7 +7847,7 @@ impl<'a> Parser<'a> { self.bump(); let (ident, item_, extra_attrs) = self.parse_item_fn(unsafety, - IsAsync::NotAsync, + respan(const_span, IsAsync::NotAsync), respan(const_span, Constness::Const), Abi::Rust)?; let prev_span = self.prev_span; @@ -7888,14 +7895,15 @@ impl<'a> Parser<'a> { // ASYNC FUNCTION ITEM let unsafety = self.parse_unsafety(); self.expect_keyword(keywords::Async)?; + let async_span = self.prev_span; self.expect_keyword(keywords::Fn)?; let fn_span = self.prev_span; let (ident, item_, extra_attrs) = self.parse_item_fn(unsafety, - IsAsync::Async { + respan(async_span, IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, - }, + }), respan(fn_span, Constness::NotConst), Abi::Rust)?; let prev_span = self.prev_span; @@ -7904,6 +7912,13 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); + if self.span.rust_2015() { + self.diagnostic().struct_span_err_with_code( + async_span, + "`async fn` is not permitted in the 2015 edition", + DiagnosticId::Error("E0670".into()) + ).emit(); + } return Ok(Some(item)); } if self.check_keyword(keywords::Unsafe) && @@ -7951,7 +7966,7 @@ impl<'a> Parser<'a> { let fn_span = self.prev_span; let (ident, item_, extra_attrs) = self.parse_item_fn(Unsafety::Normal, - IsAsync::NotAsync, + respan(fn_span, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), Abi::Rust)?; let prev_span = self.prev_span; @@ -7977,7 +7992,7 @@ impl<'a> Parser<'a> { let fn_span = self.prev_span; let (ident, item_, extra_attrs) = self.parse_item_fn(Unsafety::Unsafe, - IsAsync::NotAsync, + respan(fn_span, IsAsync::NotAsync), respan(fn_span, Constness::NotConst), abi)?; let prev_span = self.prev_span; @@ -8244,7 +8259,8 @@ impl<'a> Parser<'a> { lo: Span, visibility: Visibility ) -> PResult<'a, Option>> { - if macros_allowed && self.token.is_path_start() { + if macros_allowed && self.token.is_path_start() && + !(self.is_async_fn() && self.span.rust_2015()) { // MACRO INVOCATION ITEM let prev_span = self.prev_span; @@ -8299,7 +8315,8 @@ impl<'a> Parser<'a> { fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>, at_end: &mut bool) -> PResult<'a, Option> { - if self.token.is_path_start() { + if self.token.is_path_start() && + !(self.is_async_fn() && self.span.rust_2015()) { let prev_span = self.prev_span; let lo = self.span; let pth = self.parse_path(PathStyle::Mod)?; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index dcf9815f6d1ba..d6265ebde1bbc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3195,7 +3195,7 @@ impl<'a> State<'a> { ast::Constness::Const => self.word_nbsp("const")? } - self.print_asyncness(header.asyncness)?; + self.print_asyncness(header.asyncness.node)?; self.print_unsafety(header.unsafety)?; if header.abi != Abi::Rust { @@ -3247,7 +3247,7 @@ mod tests { ast::FnHeader { unsafety: ast::Unsafety::Normal, constness: source_map::dummy_spanned(ast::Constness::NotConst), - asyncness: ast::IsAsync::NotAsync, + asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync), abi: Abi::Rust, }, abba_ident, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a002394c710fe..46d8d772e9321 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -22,7 +22,7 @@ use syntax_pos::Span; #[derive(Copy, Clone)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - ItemFn(Ident, FnHeader, &'a Visibility, &'a Block), + ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), /// fn foo(&self) Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), @@ -149,6 +149,9 @@ pub trait Visitor<'ast>: Sized { fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) { walk_fn_ret_ty(self, ret_ty) } + fn visit_fn_header(&mut self, _header: &'ast FnHeader) { + // Nothing to do + } } #[macro_export] @@ -225,8 +228,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_ty(typ); visitor.visit_expr(expr); } - ItemKind::Fn(ref declaration, header, ref generics, ref body) => { + ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => { visitor.visit_generics(generics); + visitor.visit_fn_header(header); visitor.visit_fn(FnKind::ItemFn(item.ident, header, &item.vis, body), declaration, @@ -539,11 +543,13 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl where V: Visitor<'a>, { match kind { - FnKind::ItemFn(_, _, _, body) => { + FnKind::ItemFn(_, header, _, body) => { + visitor.visit_fn_header(header); walk_fn_decl(visitor, declaration); visitor.visit_block(body); } - FnKind::Method(_, _, _, body) => { + FnKind::Method(_, sig, _, body) => { + visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, declaration); visitor.visit_block(body); } @@ -564,6 +570,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai walk_list!(visitor, visit_expr, default); } TraitItemKind::Method(ref sig, None) => { + visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 371862465487b..f4b625f8ea2c8 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -257,7 +257,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { ); return false } - if header.asyncness.is_async() { + if header.asyncness.node.is_async() { sd.span_err( i.span, "async functions cannot be used for tests" diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/editions/edition-deny-async-fns-2015.rs new file mode 100644 index 0000000000000..2105aa5835d0d --- /dev/null +++ b/src/test/ui/editions/edition-deny-async-fns-2015.rs @@ -0,0 +1,34 @@ +// edition:2015 + +#![feature(futures_api, async_await)] + +async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + +fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition + +async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition + async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition +} + +struct Foo {} + +impl Foo { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition +} + +trait Bar { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + //~^ ERROR trait fns cannot be declared `async` +} + +fn main() { + macro_rules! accept_item { ($x:item) => {} } + + accept_item! { + async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + } + + let inside_closure = || { + async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + }; +} diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.stderr b/src/test/ui/editions/edition-deny-async-fns-2015.stderr new file mode 100644 index 0000000000000..1ad907aa7eb43 --- /dev/null +++ b/src/test/ui/editions/edition-deny-async-fns-2015.stderr @@ -0,0 +1,58 @@ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:5:1 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:7:12 + | +LL | fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:10:5 + | +LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:9:1 + | +LL | async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:32:9 + | +LL | async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:28:9 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:16:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error[E0706]: trait fns cannot be declared `async` + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^^^^^^^^^^^^^ + +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:20:5 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + +error: aborting due to 9 previous errors + +Some errors occurred: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs index 84dd1b9f814c2..b6ab8ae0a9bc7 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs +++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs @@ -2,7 +2,8 @@ #![feature(futures_api)] -async fn foo() {} //~ ERROR async fn is unstable +async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + //~^ ERROR async fn is unstable fn main() { let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr index 450b2c42f119d..58051153e1f0d 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr +++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr @@ -1,11 +1,17 @@ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/feature-gate-async-await-2015-edition.rs:5:1 + | +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition + | ^^^^^ + error[E0422]: cannot find struct, variant or union type `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:8:13 + --> $DIR/feature-gate-async-await-2015-edition.rs:9:13 | LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` | ^^^^^ not found in this scope error[E0425]: cannot find value `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:9:13 + --> $DIR/feature-gate-async-await-2015-edition.rs:10:13 | LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this scope | ^^^^^ not found in this scope @@ -13,12 +19,12 @@ LL | let _ = async || { true }; //~ ERROR cannot find value `async` in this error[E0658]: async fn is unstable (see issue #50547) --> $DIR/feature-gate-async-await-2015-edition.rs:5:1 | -LL | async fn foo() {} //~ ERROR async fn is unstable +LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition | ^^^^^^^^^^^^^^^^^ | = help: add #![feature(async_await)] to the crate attributes to enable -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0422, E0425, E0658. +Some errors occurred: E0422, E0425, E0658, E0670. For more information about an error, try `rustc --explain E0422`. diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs new file mode 100644 index 0000000000000..40642523be255 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs @@ -0,0 +1,11 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +#![feature(await_macro, async_await, futures_api, generators)] + +async fn recursive_async_function() -> () { //~ ERROR + await!(recursive_async_function()); +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr new file mode 100644 index 0000000000000..acdeabb2f9892 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-async-impl-trait-type.rs:7:40 + | +LL | async fn recursive_async_function() -> () { //~ ERROR + | ^^ expands to self-referential type + | + = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs index facb191a37081..869876dc6a88a 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs @@ -1,7 +1,7 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden. -#![feature(await_macro, async_await, futures_api, generators)] +#![feature(futures_api, generators)] fn option(i: i32) -> impl Sized { //~ ERROR if i < 0 { @@ -62,10 +62,6 @@ fn generator_hold() -> impl Sized { //~ ERROR } } -async fn recursive_async_function() -> () { //~ ERROR - await!(recursive_async_function()); -} - fn use_fn_ptr() -> impl Sized { // OK, error already reported fn_ptr() } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr index 8a8789120577e..96494229fd339 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr @@ -95,15 +95,7 @@ LL | fn generator_hold() -> impl Sized { //~ ERROR = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:65:40 - | -LL | async fn recursive_async_function() -> () { //~ ERROR - | ^^ expands to self-referential type - | - = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>` - -error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:73:26 + --> $DIR/recursive-impl-trait-type.rs:69:26 | LL | fn mutual_recursion() -> impl Sync { //~ ERROR | ^^^^^^^^^ expands to self-referential type @@ -111,13 +103,13 @@ LL | fn mutual_recursion() -> impl Sync { //~ ERROR = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:77:28 + --> $DIR/recursive-impl-trait-type.rs:73:28 | LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR | ^^^^^^^^^^ expands to self-referential type | = note: type resolves to itself -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0720`. From b7d4f96d195323cf9344a2af6720dfae3d9f299d Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 21 Feb 2019 20:21:50 -0500 Subject: [PATCH 07/38] rust-lldb: fix crash when printing empty string --- src/etc/lldb_rust_formatters.py | 2 ++ src/test/debuginfo/empty-string.rs | 33 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/debuginfo/empty-string.rs 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/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() {} From f1b88abffbbfd4625d4002d1eef1275829aba29c Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sun, 24 Feb 2019 10:01:27 -0500 Subject: [PATCH 08/38] Fix copy-pasted typo for read_string return value --- src/libstd/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 /// From 6c44bbbbaaab182196f7584810046bfef4385019 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 26 Feb 2019 09:18:22 +0900 Subject: [PATCH 09/38] Update dlmalloc to 0.1.3 --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b17a6acbaa69..1918b44a6eeb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "dlmalloc" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2092,7 +2092,7 @@ name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2114,7 +2114,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2139,7 +2139,7 @@ name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3230,7 +3230,7 @@ dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", - "dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "panic_abort 0.0.0", @@ -4000,7 +4000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f" "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" -"checksum dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d56ad71b31043818d0ee10a7fb9664882f8e45849c81647585e6a3124f185517" +"checksum dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" From eddd07cc8a92dd603e9884789fb58b2d3edd2e16 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 22 Feb 2019 13:36:04 +1100 Subject: [PATCH 10/38] Make `visit_clobber` panic-safe. --- src/libsyntax/mut_visit.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 1e5eb0992bd1b..b7d22b3d554f3 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -21,6 +21,7 @@ use syntax_pos::Span; use rustc_data_structures::sync::Lrc; use std::ops::DerefMut; +use std::{panic, process, ptr}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -305,11 +306,18 @@ pub trait MutVisitor: Sized { /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful /// when using a `flat_map_*` or `filter_map_*` method within a `visit_` -/// method. +/// method. Abort the program if the closure panics. // // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. pub fn visit_clobber(t: &mut T, f: F) where F: FnOnce(T) -> T { - unsafe { std::ptr::write(t, f(std::ptr::read(t))); } + unsafe { + // Safe because `t` is used in a read-only fashion by `read()` before + // being overwritten by `write()`. + let old_t = ptr::read(t); + let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))) + .unwrap_or_else(|_| process::abort()); + ptr::write(t, new_t); + } } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. From abd88a9e3a6014134dac0a705eae6de7448ea514 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Mon, 25 Feb 2019 19:49:49 -0800 Subject: [PATCH 11/38] Disable running several Stdio doctests * A number of `Stdio` related doc examples include running the "rev" command to illustrate piping commands. The majority of these tests are marked as `no_run` except for two tests which were not * Not running these tests is unlikely to cause any negative impact, and doing so also allows the test suite to pass in environments where the "rev" command is unavailable --- src/libstd/process.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index a2ef85016d8a2..735ce61c9bc29 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1015,7 +1015,7 @@ impl From for Stdio { /// /// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood. /// - /// ```rust + /// ```rust,no_run /// use std::process::{Command, Stdio}; /// /// let reverse = Command::new("rev") @@ -1044,7 +1044,7 @@ impl From for Stdio { /// /// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood. /// - /// ```rust + /// ```rust,no_run /// use std::process::{Command, Stdio}; /// /// let hello = Command::new("echo") From 5b975162e24d3be643a05824b6132dcb968e3fa7 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 26 Feb 2019 09:54:45 +0100 Subject: [PATCH 12/38] update scoped_tls to 1.0 --- src/librustc/Cargo.toml | 2 +- src/librustc_driver/Cargo.toml | 2 +- src/libsyntax/Cargo.toml | 2 +- src/libsyntax_pos/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index e83adad4e2a0e..e3557132a1252 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -17,7 +17,7 @@ graphviz = { path = "../libgraphviz" } jobserver = "0.1" lazy_static = "1.0.0" num_cpus = "1.0" -scoped-tls = { version = "0.1.1", features = ["nightly"] } +scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } polonius-engine = "0.6.2" rustc-rayon = "0.1.1" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 8bcda409e6663..2e6e775c52610 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -14,7 +14,7 @@ graphviz = { path = "../libgraphviz" } log = "0.4" env_logger = { version = "0.5", default-features = false } rustc-rayon = "0.1.1" -scoped-tls = { version = "0.1.1", features = ["nightly"] } +scoped-tls = "1.0" rustc = { path = "../librustc" } rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 4a0bb0302ffbc..71c2ab82f65c3 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["dylib"] bitflags = "1.0" serialize = { path = "../libserialize" } log = "0.4" -scoped-tls = "0.1" +scoped-tls = "1.0" syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 5658451c54f71..691abffbbc1af 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -13,6 +13,6 @@ crate-type = ["dylib"] serialize = { path = "../libserialize" } rustc_data_structures = { path = "../librustc_data_structures" } arena = { path = "../libarena" } -scoped-tls = { version = "0.1.1", features = ["nightly"] } +scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "0.1.2" From 992694ac4dcbc93ca249fbb9f148cc586f1d384d Mon Sep 17 00:00:00 2001 From: kenta7777 Date: Tue, 26 Feb 2019 17:54:57 +0900 Subject: [PATCH 13/38] reduce repetitions of (n << amt) >> amt --- src/librustc/ty/util.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1ba7c3bba797c..796ac372d020b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -4,6 +4,7 @@ use crate::hir::def::Def; use crate::hir::def_id::DefId; use crate::hir::map::DefPathData; use crate::hir::{self, Node}; +use crate::mir::interpret::{sign_extend, truncate}; use crate::ich::NodeIdHashingMode; use crate::traits::{self, ObligationCause}; use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; @@ -32,12 +33,12 @@ impl<'tcx> fmt::Display for Discr<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.ty.sty { ty::Int(ity) => { - let bits = ty::tls::with(|tcx| { - Integer::from_attr(&tcx, SignedInt(ity)).size().bits() + let size = ty::tls::with(|tcx| { + Integer::from_attr(&tcx, SignedInt(ity)).size() }); - let x = self.val as i128; + let x = self.val; // sign extend the raw representation to be an i128 - let x = (x << (128 - bits)) >> (128 - bits); + let x = sign_extend(x, size) as i128; write!(fmt, "{}", x) }, _ => write!(fmt, "{}", self.val), @@ -57,12 +58,12 @@ impl<'tcx> Discr<'tcx> { _ => bug!("non integer discriminant"), }; + let size = int.size(); let bit_size = int.size().bits(); let shift = 128 - bit_size; if signed { let sext = |u| { - let i = u as i128; - (i << shift) >> shift + sign_extend(u, size) as i128 }; let min = sext(1_u128 << (bit_size - 1)); let max = i128::max_value() >> shift; @@ -77,7 +78,7 @@ impl<'tcx> Discr<'tcx> { }; // zero the upper bits let val = val as u128; - let val = (val << shift) >> shift; + let val = truncate(val, size); (Self { val: val as u128, ty: self.ty, From b23fd439642a0d161d4a76d373736e3cad182339 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 10:11:41 +0100 Subject: [PATCH 14/38] Make `Unique::as_ptr`, `NonNull::dangling` and `NonNull::cast` const --- src/libcore/ptr.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 866c8d0896b3c..6186173812cb2 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2790,7 +2790,7 @@ impl Unique { } /// Acquires the underlying `*mut` pointer. - pub fn as_ptr(self) -> *mut T { + pub const fn as_ptr(self) -> *mut T { self.pointer as *mut T } @@ -2903,7 +2903,7 @@ impl NonNull { /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - pub fn dangling() -> Self { + pub const fn dangling() -> Self { unsafe { let ptr = mem::align_of::() as *mut T; NonNull::new_unchecked(ptr) @@ -2966,7 +2966,7 @@ impl NonNull { /// Cast to a pointer of another type #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] - pub fn cast(self) -> NonNull { + pub const fn cast(self) -> NonNull { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } From 56fb2873fe284ef470c468f2370418aa8bebc41a Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 26 Feb 2019 11:15:52 +0100 Subject: [PATCH 15/38] update Cargo.lock --- Cargo.lock | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b17a6acbaa69..735858d11eeda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2381,7 +2381,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_fs_util 0.0.0", "rustc_target 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", @@ -2726,7 +2726,7 @@ dependencies = [ "rustc_target 0.0.0", "rustc_traits 0.0.0", "rustc_typeck 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", @@ -3090,6 +3090,11 @@ name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -3345,7 +3350,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syntax_pos 0.0.0", @@ -3372,7 +3377,7 @@ dependencies = [ "arena 0.0.0", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4183,6 +4188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" From 2d6261904663522ee1e9ec6c9f4079e4e56ba057 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 11:58:30 +0100 Subject: [PATCH 16/38] Add `rustc_const_unstable` attribute --- src/libcore/ptr.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6186173812cb2..d00665d778fb6 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2892,6 +2892,17 @@ impl !Send for NonNull { } impl !Sync for NonNull { } impl NonNull { + /// No docs here + #[stable(feature = "nonnull", since = "1.25.0")] + #[inline] + #[cfg(stage0)] + pub fn dangling() -> Self { + unsafe { + let ptr = mem::align_of::() as *mut T; + NonNull::new_unchecked(ptr) + } + } + /// Creates a new `NonNull` that is dangling, but well-aligned. /// /// This is useful for initializing types which lazily allocate, like @@ -2903,6 +2914,8 @@ impl NonNull { /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] #[inline] + #[cfg(not(stage0))] + #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn dangling() -> Self { unsafe { let ptr = mem::align_of::() as *mut T; @@ -2963,9 +2976,21 @@ impl NonNull { &mut *self.as_ptr() } + /// No docs here + #[stable(feature = "nonnull_cast", since = "1.27.0")] + #[inline] + #[cfg(stage0)] + pub fn cast(self) -> NonNull { + unsafe { + NonNull::new_unchecked(self.as_ptr() as *mut U) + } + } + /// Cast to a pointer of another type #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] + #[cfg(not(stage0))] + #[rustc_const_unstable(feature = "const_ptr_nonnull")] pub const fn cast(self) -> NonNull { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) From 4839d8c544232df8fa1cb55d306a936fc098ce9c Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 11:58:44 +0100 Subject: [PATCH 17/38] Add tests --- src/test/run-pass/consts/const-ptr-nonnull.rs | 22 +++++++++++++++++ src/test/run-pass/consts/const-ptr-unique.rs | 15 ++++++++++++ src/test/ui/consts/const-ptr-nonnull.rs | 9 +++++++ src/test/ui/consts/const-ptr-nonnull.stderr | 24 +++++++++++++++++++ src/test/ui/consts/const-ptr-unique.rs | 9 +++++++ src/test/ui/consts/const-ptr-unique.stderr | 13 ++++++++++ 6 files changed, 92 insertions(+) create mode 100644 src/test/run-pass/consts/const-ptr-nonnull.rs create mode 100644 src/test/run-pass/consts/const-ptr-unique.rs create mode 100644 src/test/ui/consts/const-ptr-nonnull.rs create mode 100644 src/test/ui/consts/const-ptr-nonnull.stderr create mode 100644 src/test/ui/consts/const-ptr-unique.rs create mode 100644 src/test/ui/consts/const-ptr-unique.stderr diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs new file mode 100644 index 0000000000000..62f10fb484177 --- /dev/null +++ b/src/test/run-pass/consts/const-ptr-nonnull.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(const_ptr_nonnull)] + +use std::ptr::NonNull; + +const fn dangling() -> NonNull { + NonNull::dangling() +} + +const fn cast(non_null: NonNull) -> NonNull { + non_null.cast() +} + +pub fn main() { + assert_eq!(dangling(), NonNull::dangling()); + + let mut i: i32 = 10; + let non_null_t = NonNull::new(&mut i).unwrap(); + let non_null_u: NonNull = cast(non_null_t); + assert_eq!(non_null_t.as_ptr(), non_null_u.as_ptr() as *mut i32); +} diff --git a/src/test/run-pass/consts/const-ptr-unique.rs b/src/test/run-pass/consts/const-ptr-unique.rs new file mode 100644 index 0000000000000..4374bb81b4ee8 --- /dev/null +++ b/src/test/run-pass/consts/const-ptr-unique.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(ptr_internals)] + +use std::ptr::Unique; + +const fn as_ptr(ptr: Unique) -> *mut T { + ptr.as_ptr() +} + +pub fn main() { + let mut i: i32 = 10; + let unique = Unique::new(&mut i).unwrap(); + assert_eq!(unique.as_ptr(), as_ptr(unique)); +} diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs new file mode 100644 index 0000000000000..9502b619b6613 --- /dev/null +++ b/src/test/ui/consts/const-ptr-nonnull.rs @@ -0,0 +1,9 @@ +use std::ptr::NonNull; + +fn main() { + let x: &'static NonNull = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough + + let mut i: i32 = 10; + let non_null = NonNull::new(&mut i).unwrap(); + let x: &'static NonNull = &(non_null.cast()); //~ ERROR borrowed value does not live long enough +} diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr new file mode 100644 index 0000000000000..e670528210849 --- /dev/null +++ b/src/test/ui/consts/const-ptr-nonnull.stderr @@ -0,0 +1,24 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-ptr-nonnull.rs:4:37 + | +LL | let x: &'static NonNull = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/const-ptr-nonnull.rs:8:37 + | +LL | let x: &'static NonNull = &(non_null.cast()); //~ ERROR borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs new file mode 100644 index 0000000000000..792d1854b7899 --- /dev/null +++ b/src/test/ui/consts/const-ptr-unique.rs @@ -0,0 +1,9 @@ +#![feature(ptr_internals)] + +use std::ptr::Unique; + +fn main() { + let mut i: u32 = 10; + let unique = Unique::new(&mut i).unwrap(); + let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough +} diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr new file mode 100644 index 0000000000000..32cb862b3c3e8 --- /dev/null +++ b/src/test/ui/consts/const-ptr-unique.stderr @@ -0,0 +1,13 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/const-ptr-unique.rs:8:33 + | +LL | let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From 6375efc822eab92a42ce0382ca9597d8430c4efd Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Tue, 26 Feb 2019 20:06:31 +0900 Subject: [PATCH 18/38] Update string_cache_codegen to 0.4.2 --- Cargo.lock | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b17a6acbaa69..64db279862d45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1399,7 +1399,7 @@ dependencies = [ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1936,14 +1936,6 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro2" version = "0.4.24" @@ -2015,14 +2007,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.6.10" @@ -3255,19 +3239,19 @@ dependencies = [ "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string_cache_codegen" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4124,7 +4108,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" -"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" @@ -4132,7 +4115,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum racer 2.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d634483bed41bb116122b84ffe0ef8740345c2ceb2784ce86c33499700eb13a7" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" @@ -4201,7 +4183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" -"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" +"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e" From 278cb91346dcd043734ec250fbcc4b87ae93aef1 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 13:03:40 +0100 Subject: [PATCH 19/38] Satisfy tidy --- src/libcore/ptr.rs | 2 +- src/test/run-pass/consts/const-ptr-nonnull.rs | 2 +- src/test/ui/consts/const-ptr-nonnull.rs | 8 +++++--- src/test/ui/consts/const-ptr-nonnull.stderr | 7 ++++--- src/test/ui/consts/const-ptr-unique.rs | 3 ++- src/test/ui/consts/const-ptr-unique.stderr | 3 ++- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d00665d778fb6..d817dacadca9c 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2902,7 +2902,7 @@ impl NonNull { NonNull::new_unchecked(ptr) } } - + /// Creates a new `NonNull` that is dangling, but well-aligned. /// /// This is useful for initializing types which lazily allocate, like diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs index 62f10fb484177..70d22c5e7147f 100644 --- a/src/test/run-pass/consts/const-ptr-nonnull.rs +++ b/src/test/run-pass/consts/const-ptr-nonnull.rs @@ -14,7 +14,7 @@ const fn cast(non_null: NonNull) -> NonNull { pub fn main() { assert_eq!(dangling(), NonNull::dangling()); - + let mut i: i32 = 10; let non_null_t = NonNull::new(&mut i).unwrap(); let non_null_u: NonNull = cast(non_null_t); diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs index 9502b619b6613..54e743aa32e23 100644 --- a/src/test/ui/consts/const-ptr-nonnull.rs +++ b/src/test/ui/consts/const-ptr-nonnull.rs @@ -1,9 +1,11 @@ use std::ptr::NonNull; fn main() { - let x: &'static NonNull = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough - + let x: &'static NonNull = &(NonNull::dangling()); + //~^ ERROR borrowed value does not live long enough + let mut i: i32 = 10; let non_null = NonNull::new(&mut i).unwrap(); - let x: &'static NonNull = &(non_null.cast()); //~ ERROR borrowed value does not live long enough + let x: &'static NonNull = &(non_null.cast()); + //~^ ERROR borrowed value does not live long enough } diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr index e670528210849..a9476dda6d320 100644 --- a/src/test/ui/consts/const-ptr-nonnull.stderr +++ b/src/test/ui/consts/const-ptr-nonnull.stderr @@ -1,7 +1,7 @@ error[E0597]: borrowed value does not live long enough --> $DIR/const-ptr-nonnull.rs:4:37 | -LL | let x: &'static NonNull = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough +LL | let x: &'static NonNull = &(NonNull::dangling()); | ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough ... LL | } @@ -10,10 +10,11 @@ LL | } = note: borrowed value must be valid for the static lifetime... error[E0597]: borrowed value does not live long enough - --> $DIR/const-ptr-nonnull.rs:8:37 + --> $DIR/const-ptr-nonnull.rs:9:37 | -LL | let x: &'static NonNull = &(non_null.cast()); //~ ERROR borrowed value does not live long enough +LL | let x: &'static NonNull = &(non_null.cast()); | ^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | //~^ ERROR borrowed value does not live long enough LL | } | - temporary value only lives until here | diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs index 792d1854b7899..be44a24181606 100644 --- a/src/test/ui/consts/const-ptr-unique.rs +++ b/src/test/ui/consts/const-ptr-unique.rs @@ -5,5 +5,6 @@ use std::ptr::Unique; fn main() { let mut i: u32 = 10; let unique = Unique::new(&mut i).unwrap(); - let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough + let x: &'static *mut u32 = &(unique.as_ptr()); + //~^ ERROR borrowed value does not live long enough } diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr index 32cb862b3c3e8..141465bf184d0 100644 --- a/src/test/ui/consts/const-ptr-unique.stderr +++ b/src/test/ui/consts/const-ptr-unique.stderr @@ -1,8 +1,9 @@ error[E0597]: borrowed value does not live long enough --> $DIR/const-ptr-unique.rs:8:33 | -LL | let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough +LL | let x: &'static *mut u32 = &(unique.as_ptr()); | ^^^^^^^^^^^^^^^^^ temporary value does not live long enough +LL | //~^ ERROR borrowed value does not live long enough LL | } | - temporary value only lives until here | From baea3c7ae9588adb6500acfbf418e58c8edb0a7e Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 14:18:43 +0100 Subject: [PATCH 20/38] Use `cfg_attr` to prevent duplication --- src/libcore/ptr.rs | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d817dacadca9c..3e1773ff9d25c 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2892,17 +2892,6 @@ impl !Send for NonNull { } impl !Sync for NonNull { } impl NonNull { - /// No docs here - #[stable(feature = "nonnull", since = "1.25.0")] - #[inline] - #[cfg(stage0)] - pub fn dangling() -> Self { - unsafe { - let ptr = mem::align_of::() as *mut T; - NonNull::new_unchecked(ptr) - } - } - /// Creates a new `NonNull` that is dangling, but well-aligned. /// /// This is useful for initializing types which lazily allocate, like @@ -2914,8 +2903,7 @@ impl NonNull { /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - #[cfg(not(stage0))] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] + #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))] pub const fn dangling() -> Self { unsafe { let ptr = mem::align_of::() as *mut T; @@ -2976,21 +2964,10 @@ impl NonNull { &mut *self.as_ptr() } - /// No docs here - #[stable(feature = "nonnull_cast", since = "1.27.0")] - #[inline] - #[cfg(stage0)] - pub fn cast(self) -> NonNull { - unsafe { - NonNull::new_unchecked(self.as_ptr() as *mut U) - } - } - /// Cast to a pointer of another type #[stable(feature = "nonnull_cast", since = "1.27.0")] #[inline] - #[cfg(not(stage0))] - #[rustc_const_unstable(feature = "const_ptr_nonnull")] + #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))] pub const fn cast(self) -> NonNull { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) From c5f3830e63e1a222f07234ac9ea012dee96220bb Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 26 Feb 2019 14:19:07 +0100 Subject: [PATCH 21/38] Use const eval instead of const fn --- src/test/run-pass/consts/const-ptr-nonnull.rs | 17 ++++++----------- src/test/run-pass/consts/const-ptr-unique.rs | 10 +++++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs index 70d22c5e7147f..91624e92fbe75 100644 --- a/src/test/run-pass/consts/const-ptr-nonnull.rs +++ b/src/test/run-pass/consts/const-ptr-nonnull.rs @@ -4,19 +4,14 @@ use std::ptr::NonNull; -const fn dangling() -> NonNull { - NonNull::dangling() -} +const DANGLING: NonNull = NonNull::dangling(); +const CASTED: NonNull = NonNull::cast(NonNull::::dangling()); -const fn cast(non_null: NonNull) -> NonNull { - non_null.cast() +fn ident(ident: T) -> T { + ident } pub fn main() { - assert_eq!(dangling(), NonNull::dangling()); - - let mut i: i32 = 10; - let non_null_t = NonNull::new(&mut i).unwrap(); - let non_null_u: NonNull = cast(non_null_t); - assert_eq!(non_null_t.as_ptr(), non_null_u.as_ptr() as *mut i32); + assert_eq!(DANGLING, ident(NonNull::dangling())); + assert_eq!(CASTED, ident(NonNull::dangling())); } diff --git a/src/test/run-pass/consts/const-ptr-unique.rs b/src/test/run-pass/consts/const-ptr-unique.rs index 4374bb81b4ee8..eb371ab184166 100644 --- a/src/test/run-pass/consts/const-ptr-unique.rs +++ b/src/test/run-pass/consts/const-ptr-unique.rs @@ -4,12 +4,12 @@ use std::ptr::Unique; -const fn as_ptr(ptr: Unique) -> *mut T { - ptr.as_ptr() +const PTR: *mut u32 = Unique::empty().as_ptr(); + +fn ident(ident: T) -> T { + ident } pub fn main() { - let mut i: i32 = 10; - let unique = Unique::new(&mut i).unwrap(); - assert_eq!(unique.as_ptr(), as_ptr(unique)); + assert_eq!(PTR, ident(Unique::::empty().as_ptr())); } From 998896c036cca6ed984f39fe28bb867055432167 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 26 Feb 2019 16:10:28 +0100 Subject: [PATCH 22/38] Clarify `rotate_{left,right}` docs I wondered what the `<>`! +Please note this isn't the same operation as the `>>` shifting operator! # Examples @@ -2300,7 +2300,7 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " concat!("Shifts the bits to the left by a specified amount, `n`, wrapping the truncated bits to the end of the resulting integer. -Please note this isn't the same operation as `<<`! +Please note this isn't the same operation as the `<<` shifting operator! # Examples @@ -2324,7 +2324,7 @@ assert_eq!(n.rotate_left(", $rot, "), m); wrapping the truncated bits to the beginning of the resulting integer. -Please note this isn't the same operation as `>>`! +Please note this isn't the same operation as the `>>` shifting operator! # Examples diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 50e189c9e3640..9cd5108ade411 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -429,7 +429,8 @@ assert_eq!(n.trailing_zeros(), 3); /// wrapping the truncated bits to the end of the resulting /// integer. /// - /// Please note this isn't the same operation as `>>`! + /// Please note this isn't the same operation as the `>>` shifting + /// operator! /// /// # Examples /// @@ -454,7 +455,8 @@ assert_eq!(n.trailing_zeros(), 3); /// wrapping the truncated bits to the beginning of the resulting /// integer. /// - /// Please note this isn't the same operation as `<<`! + /// Please note this isn't the same operation as the `<<` shifting + /// operator! /// /// # Examples /// From 9b4055b30200caf366d387624fd5bbb03de8da13 Mon Sep 17 00:00:00 2001 From: Angelos Oikonomopoulos Date: Tue, 26 Feb 2019 16:48:12 +0100 Subject: [PATCH 23/38] Normalize the type Self resolves to in an impl This is required at the very least in order to evaluate associated constants for arrays (see #58212). --- src/librustc_typeck/astconv.rs | 3 ++- src/test/run-pass/issues/issue-58212.rs | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issues/issue-58212.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index db63f2aafbc24..c52ff8bf650cd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1700,7 +1700,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // `Self` in impl (we know the concrete type). assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - tcx.at(span).type_of(def_id) + // Try to evaluate any array length constants + self.normalize_ty(span, tcx.at(span).type_of(def_id)) } Def::SelfTy(Some(_), None) => { // `Self` in trait. diff --git a/src/test/run-pass/issues/issue-58212.rs b/src/test/run-pass/issues/issue-58212.rs new file mode 100644 index 0000000000000..76437630309af --- /dev/null +++ b/src/test/run-pass/issues/issue-58212.rs @@ -0,0 +1,13 @@ +trait FromUnchecked { + unsafe fn from_unchecked(); +} + +impl FromUnchecked for [u8; 1] { + unsafe fn from_unchecked() { + let mut array: Self = std::mem::uninitialized(); + let _ptr = &mut array as *mut [u8] as *mut u8; + } +} + +fn main() { +} From c1f3d1520efc91ec79dfafd6ab0e679872092487 Mon Sep 17 00:00:00 2001 From: Adonis Date: Sat, 2 Feb 2019 12:03:38 +0100 Subject: [PATCH 24/38] Changing error message to reflect changes with the 2018 edition Signed-off-by: Adonis Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Update src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr Co-Authored-By: asettouf Update src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr Co-Authored-By: asettouf Stabilize split_ascii_whitespace Tracking issue FCP to merge: https://github.com/rust-lang/rust/issues/48656#issuecomment-442372750 fix stabilization order of uniform_paths. hir: add HirId to main Hir nodes Fix `std::os::fortanix_sgx::usercalls::raw::UsercallNrs` Fixes https://github.com/fortanix/rust-sgx/issues/88 Update src/libsyntax/ext/tt/quoted.rs Co-Authored-By: asettouf Revert "Merge remote-tracking branch 'upstream/master'" This reverts commit 751f05bd155e2c55d4177fe8211df634faf3a644, reversing changes made to 545a3e62b0cb473108869a61b271bc589afb49da. --- src/libsyntax/ext/tt/quoted.rs | 18 ++++++++++++------ ...macro-at-most-once-rep-2015-ques-rep.stderr | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index b56871a18857f..43d279980f6ea 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -474,11 +474,13 @@ where // #1 is a separator and #2 should be a KleepeOp. // (N.B. We need to advance the input iterator.) match parse_kleene_op(input, span) { - // #2 is `?`, which is not allowed as a Kleene op in 2015 edition. + // #2 is `?`, which is not allowed as a Kleene op in 2015 edition, + // but is allowed in the 2018 edition. Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { sess.span_diagnostic .struct_span_err(op2_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator") + .note("`?` is not a macro repetition operator in the 2015 edition, \ + but is accepted in the 2018 edition") .emit(); // Return a dummy @@ -506,10 +508,12 @@ where Err(_) => op1_span, } } else { - // `?` is not allowed as a Kleene op in 2015 + // `?` is not allowed as a Kleene op in 2015, + // but is allowed in the 2018 edition sess.span_diagnostic .struct_span_err(op1_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator") + .note("`?` is not a macro repetition operator in the 2015 edition, \ + but is accepted in the 2018 edition") .emit(); // Return a dummy @@ -519,11 +523,13 @@ where // #1 is a separator followed by #2, a KleeneOp Ok(Err((tok, span))) => match parse_kleene_op(input, span) { - // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition. + // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition, + // but is allowed in the 2018 edition Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { sess.span_diagnostic .struct_span_err(op2_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator") + .note("`?` is not a macro repetition operator in the 2015 edition, \ + but is accepted in the 2018 edition") .emit(); // Return a dummy diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr index b27b60459d633..cb0a9163b7470 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr @@ -4,7 +4,7 @@ error: expected `*` or `+` LL | ($(a)?) => {} //~ERROR expected `*` or `+` | ^ | - = note: `?` is not a macro repetition operator + = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition error: expected `*` or `+` --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:10:11 @@ -12,7 +12,7 @@ error: expected `*` or `+` LL | ($(a),?) => {} //~ERROR expected `*` or `+` | ^ | - = note: `?` is not a macro repetition operator + = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition error: aborting due to 2 previous errors From 5d8fd8b6cd1c8935bcc67b0763efba431e2eff73 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 26 Feb 2019 22:42:50 +0300 Subject: [PATCH 25/38] Mention `unwind(aborts)` in diagnostics for `#[unwind]` Simplify input validation for `#[unwind]`, add tests --- src/libsyntax/attr/builtin.rs | 48 +++++++------------ src/libsyntax/feature_gate.rs | 2 +- src/test/ui/malformed/malformed-unwind-1.rs | 11 +++++ .../ui/malformed/malformed-unwind-1.stderr | 14 ++++++ src/test/ui/malformed/malformed-unwind-2.rs | 11 +++++ .../ui/malformed/malformed-unwind-2.stderr | 15 ++++++ 6 files changed, 69 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/malformed/malformed-unwind-1.rs create mode 100644 src/test/ui/malformed/malformed-unwind-1.stderr create mode 100644 src/test/ui/malformed/malformed-unwind-2.rs create mode 100644 src/test/ui/malformed/malformed-unwind-2.stderr diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index e84adc01cf04a..f7a000935caf0 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -7,7 +7,7 @@ use crate::parse::ParseSess; use errors::{Applicability, Handler}; use syntax_pos::{symbol::Symbol, Span}; -use super::{list_contains_name, mark_used, MetaItemKind}; +use super::{mark_used, MetaItemKind}; enum AttrError { MultipleItem(Name), @@ -79,40 +79,26 @@ pub enum UnwindAttr { /// Determine what `#[unwind]` attribute is present in `attrs`, if any. pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option { - let syntax_error = |attr: &Attribute| { - mark_used(attr); - diagnostic.map(|d| { - span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute"); - }); - None - }; - attrs.iter().fold(None, |ia, attr| { - if attr.path != "unwind" { - return ia; - } - let meta = match attr.meta() { - Some(meta) => meta.node, - None => return ia, - }; - match meta { - MetaItemKind::Word => { - syntax_error(attr) - } - MetaItemKind::List(ref items) => { - mark_used(attr); - if items.len() != 1 { - syntax_error(attr) - } else if list_contains_name(&items[..], "allowed") { - Some(UnwindAttr::Allowed) - } else if list_contains_name(&items[..], "aborts") { - Some(UnwindAttr::Aborts) - } else { - syntax_error(attr) + if attr.check_name("unwind") { + if let Some(meta) = attr.meta() { + if let MetaItemKind::List(items) = meta.node { + if items.len() == 1 { + if items[0].check_name("allowed") { + return Some(UnwindAttr::Allowed); + } else if items[0].check_name("aborts") { + return Some(UnwindAttr::Aborts); + } + } + + diagnostic.map(|d| { + span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute"); + }); } } - _ => ia, } + + ia }) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index cc1953e69d4ca..93c6de274eeea 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1173,7 +1173,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu "dropck_eyepatch", "may_dangle has unstable semantics and may be removed in the future", cfg_fn!(dropck_eyepatch))), - ("unwind", Whitelisted, template!(List: "allowed"), Gated(Stability::Unstable, + ("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable, "unwind_attributes", "#[unwind] is experimental", cfg_fn!(unwind_attributes))), diff --git a/src/test/ui/malformed/malformed-unwind-1.rs b/src/test/ui/malformed/malformed-unwind-1.rs new file mode 100644 index 0000000000000..e34c288c027c2 --- /dev/null +++ b/src/test/ui/malformed/malformed-unwind-1.rs @@ -0,0 +1,11 @@ +#![feature(unwind_attributes)] + +#[unwind] +//~^ ERROR attribute must be of the form +extern "C" fn f1() {} + +#[unwind = ""] +//~^ ERROR attribute must be of the form +extern "C" fn f2() {} + +fn main() {} diff --git a/src/test/ui/malformed/malformed-unwind-1.stderr b/src/test/ui/malformed/malformed-unwind-1.stderr new file mode 100644 index 0000000000000..852136eed91bd --- /dev/null +++ b/src/test/ui/malformed/malformed-unwind-1.stderr @@ -0,0 +1,14 @@ +error: attribute must be of the form `#[unwind(allowed|aborts)]` + --> $DIR/malformed-unwind-1.rs:3:1 + | +LL | #[unwind] + | ^^^^^^^^^ + +error: attribute must be of the form `#[unwind(allowed|aborts)]` + --> $DIR/malformed-unwind-1.rs:7:1 + | +LL | #[unwind = ""] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/malformed/malformed-unwind-2.rs b/src/test/ui/malformed/malformed-unwind-2.rs new file mode 100644 index 0000000000000..d4955b4330930 --- /dev/null +++ b/src/test/ui/malformed/malformed-unwind-2.rs @@ -0,0 +1,11 @@ +#![feature(unwind_attributes)] + +#[unwind(allowed, aborts)] +//~^ ERROR malformed `#[unwind]` attribute +extern "C" fn f1() {} + +#[unwind(unsupported)] +//~^ ERROR malformed `#[unwind]` attribute +extern "C" fn f2() {} + +fn main() {} diff --git a/src/test/ui/malformed/malformed-unwind-2.stderr b/src/test/ui/malformed/malformed-unwind-2.stderr new file mode 100644 index 0000000000000..88fc4e00a2fd3 --- /dev/null +++ b/src/test/ui/malformed/malformed-unwind-2.stderr @@ -0,0 +1,15 @@ +error[E0633]: malformed `#[unwind]` attribute + --> $DIR/malformed-unwind-2.rs:3:1 + | +LL | #[unwind(allowed, aborts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0633]: malformed `#[unwind]` attribute + --> $DIR/malformed-unwind-2.rs:7:1 + | +LL | #[unwind(unsupported)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0633`. From 6fd716d8ca6fd90a0c0240e2e4e4f7488d98a42b Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:07:12 +0000 Subject: [PATCH 26/38] Add a test for #10876 --- src/test/ui/borrowck/issue-10876.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/ui/borrowck/issue-10876.rs diff --git a/src/test/ui/borrowck/issue-10876.rs b/src/test/ui/borrowck/issue-10876.rs new file mode 100644 index 0000000000000..d8fff5f17760a --- /dev/null +++ b/src/test/ui/borrowck/issue-10876.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(nll)] + +enum Nat { + S(Box), + Z +} +fn test(x: &mut Nat) { + let mut p = &mut *x; + loop { + match p { + &mut Nat::Z => break, + &mut Nat::S(ref mut n) => p = &mut *n + } + } +} + +fn main() {} From 26e5fc37fa81003bdba71f0f4e3a83cc722d3b41 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:54:49 +0000 Subject: [PATCH 27/38] Add tests for #26448 --- src/test/ui/issues/issue-26448-1.rs | 13 +++++++++++++ src/test/ui/issues/issue-26448-2.rs | 21 +++++++++++++++++++++ src/test/ui/issues/issue-26448-3.rs | 25 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/test/ui/issues/issue-26448-1.rs create mode 100644 src/test/ui/issues/issue-26448-2.rs create mode 100644 src/test/ui/issues/issue-26448-3.rs diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/issues/issue-26448-1.rs new file mode 100644 index 0000000000000..7d2d75bf2e878 --- /dev/null +++ b/src/test/ui/issues/issue-26448-1.rs @@ -0,0 +1,13 @@ +// run-pass + +pub trait Foo { + fn foo(self) -> T; +} + +impl<'a, T> Foo for &'a str where &'a str: Into { + fn foo(self) -> T { + panic!(); + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs new file mode 100644 index 0000000000000..17e7c1f977a6d --- /dev/null +++ b/src/test/ui/issues/issue-26448-2.rs @@ -0,0 +1,21 @@ +// run-pass + +pub struct Bar { + items: Vec<&'static str>, + inner: T, +} + +pub trait IntoBar { + fn into_bar(self) -> Bar; +} + +impl<'a, T> IntoBar for &'a str where &'a str: Into { + fn into_bar(self) -> Bar { + Bar { + items: Vec::new(), + inner: self.into(), + } + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs new file mode 100644 index 0000000000000..e57352e57f4fc --- /dev/null +++ b/src/test/ui/issues/issue-26448-3.rs @@ -0,0 +1,25 @@ +// run-pass + +pub struct Item { + _inner: &'static str, +} + +pub struct Bar { + items: Vec, + inner: T, +} + +pub trait IntoBar { + fn into_bar(self) -> Bar; +} + +impl<'a, T> IntoBar for &'a str where &'a str: Into { + fn into_bar(self) -> Bar { + Bar { + items: Vec::new(), + inner: self.into(), + } + } +} + +fn main() {} From d6448a45ecbdd4bc8cd43fac5f1e97db40e69280 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:00 +0000 Subject: [PATCH 28/38] Add a test for #26619 --- src/test/ui/issues/issue-26619.rs | 24 ++++++++++++++++++++++++ src/test/ui/issues/issue-26619.stderr | 12 ++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/ui/issues/issue-26619.rs create mode 100644 src/test/ui/issues/issue-26619.stderr diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs new file mode 100644 index 0000000000000..cd89c674e4996 --- /dev/null +++ b/src/test/ui/issues/issue-26619.rs @@ -0,0 +1,24 @@ +#![feature(slice_patterns)] + +pub struct History<'a> { pub _s: &'a str } + +impl<'a> History<'a> { + pub fn get_page(&self) { + for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) { + //~^ ERROR borrowed value does not live long enough + println!("{:?}", s); + } + } + + fn make_entry(&self, s: &'a String) -> Option<&str> { + let parts: Vec<_> = s.split('|').collect(); + println!("{:?} -> {:?}", s, parts); + + if let [commit, ..] = &parts[..] { Some(commit) } else { None } + } +} + +fn main() { + let h = History{ _s: "" }; + h.get_page(); +} diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr new file mode 100644 index 0000000000000..3ac6c4e308d21 --- /dev/null +++ b/src/test/ui/issues/issue-26619.stderr @@ -0,0 +1,12 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/issue-26619.rs:7:66 + | +LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) { + | ^^^^^^^^ -- temporary value needs to live until here + | | | + | | temporary value dropped here while still borrowed + | temporary value does not live long enough + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From eef9612c90afca193a4cbb25d83583c6bb368541 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:08 +0000 Subject: [PATCH 29/38] Add a test for #44127 --- src/test/ui/issues/issue-44127.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/ui/issues/issue-44127.rs diff --git a/src/test/ui/issues/issue-44127.rs b/src/test/ui/issues/issue-44127.rs new file mode 100644 index 0000000000000..21b2e68264a14 --- /dev/null +++ b/src/test/ui/issues/issue-44127.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(decl_macro)] + +pub struct Foo { + bar: u32, +} +pub macro pattern($a:pat) { + Foo { bar: $a } +} + +fn main() { + match (Foo { bar: 3 }) { + pattern!(3) => println!("Test OK"), + _ => unreachable!(), + } +} From ad6940db8d9074b50c03748b4c16f3db357f4a5c Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:16 +0000 Subject: [PATCH 30/38] Add a test for #44255 --- src/test/ui/issues/issue-44255.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/ui/issues/issue-44255.rs diff --git a/src/test/ui/issues/issue-44255.rs b/src/test/ui/issues/issue-44255.rs new file mode 100644 index 0000000000000..2245032043257 --- /dev/null +++ b/src/test/ui/issues/issue-44255.rs @@ -0,0 +1,29 @@ +// run-pass + +use std::marker::PhantomData; + +fn main() { + let _arr = [1; >::VAL]; +} + +trait TypeVal { + const VAL: T; +} + +struct Five; + +impl TypeVal for Five { + const VAL: usize = 5; +} + +struct Multiply { + _n: PhantomData, + _m: PhantomData, +} + +impl TypeVal for Multiply + where N: TypeVal, + M: TypeVal, +{ + const VAL: usize = N::VAL * M::VAL; +} From 4e5f7805c8a79f10f5518fdb8fe82132ce4cbd43 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:25 +0000 Subject: [PATCH 31/38] Add a test for #46101 --- src/test/ui/issues/issue-46101.rs | 4 ++++ src/test/ui/issues/issue-46101.stderr | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/issues/issue-46101.rs create mode 100644 src/test/ui/issues/issue-46101.stderr diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs new file mode 100644 index 0000000000000..2d9111e9b3a98 --- /dev/null +++ b/src/test/ui/issues/issue-46101.rs @@ -0,0 +1,4 @@ +#![feature(use_extern_macros)] +trait Foo {} +#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro +struct S; diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr new file mode 100644 index 0000000000000..f8b95d7a23bf2 --- /dev/null +++ b/src/test/ui/issues/issue-46101.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: partially resolved path in a derive macro + --> $DIR/issue-46101.rs:3:10 + | +LL | #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro + | ^^^^^^^^^^^^^ partially resolved path in a derive macro + +error[E0601]: `main` function not found in crate `issue_46101` + | + = note: consider adding a `main` function to `$DIR/issue-46101.rs` + +error: aborting due to 2 previous errors + +Some errors occurred: E0433, E0601. +For more information about an error, try `rustc --explain E0433`. From d76a632bdd60bd77d64cf8ae4ef6b33695fb251e Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:34 +0000 Subject: [PATCH 32/38] Add a test for #55731 --- src/test/ui/issues/issue-55731.rs | 52 +++++++++++++++++++++++++++ src/test/ui/issues/issue-55731.stderr | 12 +++++++ 2 files changed, 64 insertions(+) create mode 100644 src/test/ui/issues/issue-55731.rs create mode 100644 src/test/ui/issues/issue-55731.stderr diff --git a/src/test/ui/issues/issue-55731.rs b/src/test/ui/issues/issue-55731.rs new file mode 100644 index 0000000000000..7b4f4e2cd3b40 --- /dev/null +++ b/src/test/ui/issues/issue-55731.rs @@ -0,0 +1,52 @@ +use std::marker::PhantomData; + +trait DistributedIterator { + fn reduce(self) + where + Self: Sized, + { + unreachable!() + } +} + +trait DistributedIteratorMulti { + type Item; +} + +struct Connect(PhantomData); +impl DistributedIteratorMulti<&'a ()>> DistributedIterator for Connect where {} + +struct Cloned(PhantomData); +impl<'a, Source> DistributedIteratorMulti<&'a Source> for Cloned<&'a Source> { + type Item = (); +} + +struct Map { + i: I, + f: F, +} +impl, F, Source> DistributedIteratorMulti for Map +where + F: A<>::Item>, +{ + type Item = (); +} + +trait A {} + +struct X; +impl A<()> for X {} + +fn multi(_reducer: I) +where + I: for<'a> DistributedIteratorMulti<&'a ()>, +{ + DistributedIterator::reduce(Connect::(PhantomData)) +} + +fn main() { + multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough + i: Cloned(PhantomData), + f: X, + }); +} diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr new file mode 100644 index 0000000000000..67f2053de1ebe --- /dev/null +++ b/src/test/ui/issues/issue-55731.stderr @@ -0,0 +1,12 @@ +error: implementation of `DistributedIteratorMulti` is not general enough + --> $DIR/issue-55731.rs:48:5 + | +LL | multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough + | ^^^^^ + | + = note: Due to a where-clause on `multi`, + = note: `Map, X>` must implement `DistributedIteratorMulti<&'0 ()>`, for any lifetime `'0` + = note: but `Map, X>` actually implements `DistributedIteratorMulti<&'1 ()>`, for some specific lifetime `'1` + +error: aborting due to previous error + From 0b2f320f2350c9ae8423a44e058ce5afa298e36e Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:55:43 +0000 Subject: [PATCH 33/38] Add a test for #57781 --- src/test/ui/issues/issue-57781.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/ui/issues/issue-57781.rs diff --git a/src/test/ui/issues/issue-57781.rs b/src/test/ui/issues/issue-57781.rs new file mode 100644 index 0000000000000..f5015aaf5d81f --- /dev/null +++ b/src/test/ui/issues/issue-57781.rs @@ -0,0 +1,20 @@ +// run-pass + +use std::cell::UnsafeCell; +use std::collections::HashMap; + +struct OnceCell { + _value: UnsafeCell>, +} + +impl OnceCell { + const INIT: OnceCell = OnceCell { + _value: UnsafeCell::new(None), + }; +} + +pub fn crash() { + let _ = OnceCell::>::INIT; +} + +fn main() {} From 41d4ec606b8027e1f92180c80aaa72aa5afe84bb Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:56:10 +0000 Subject: [PATCH 34/38] Add a test for #22892 --- src/test/ui/asm/invalid-inline-asm.rs | 9 +++++++++ src/test/ui/asm/invalid-inline-asm.stderr | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/ui/asm/invalid-inline-asm.rs create mode 100644 src/test/ui/asm/invalid-inline-asm.stderr diff --git a/src/test/ui/asm/invalid-inline-asm.rs b/src/test/ui/asm/invalid-inline-asm.rs new file mode 100644 index 0000000000000..1dcded0be0b74 --- /dev/null +++ b/src/test/ui/asm/invalid-inline-asm.rs @@ -0,0 +1,9 @@ +#![feature(asm)] + +fn main() { + let byte = 0; + let port = 0x80; + + unsafe { asm!("out %al, %dx" :: "a" (byte), "d" (port) :: "volatile"); } + //~^ ERROR couldn't allocate input reg for constraint 'a' +} diff --git a/src/test/ui/asm/invalid-inline-asm.stderr b/src/test/ui/asm/invalid-inline-asm.stderr new file mode 100644 index 0000000000000..11a32d3141e08 --- /dev/null +++ b/src/test/ui/asm/invalid-inline-asm.stderr @@ -0,0 +1,8 @@ +error: couldn't allocate input reg for constraint 'a' + --> $DIR/invalid-inline-asm.rs:7:14 + | +LL | unsafe { asm!("out %al, %dx" :: "a" (byte), "d" (port) :: "volatile"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From caa07999f4fff6937848b3c0cb33c091b53d900d Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:56:27 +0000 Subject: [PATCH 35/38] Add a test for #28587 --- src/test/ui/asm/invalid-inline-asm-2.rs | 10 ++++++++++ src/test/ui/asm/invalid-inline-asm-2.stderr | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/asm/invalid-inline-asm-2.rs create mode 100644 src/test/ui/asm/invalid-inline-asm-2.stderr diff --git a/src/test/ui/asm/invalid-inline-asm-2.rs b/src/test/ui/asm/invalid-inline-asm-2.rs new file mode 100644 index 0000000000000..7b3f1cdd67949 --- /dev/null +++ b/src/test/ui/asm/invalid-inline-asm-2.rs @@ -0,0 +1,10 @@ +#![feature(asm)] + +fn main() { + let a: usize; + + unsafe { + asm!("" : "=d"(a) : : : ); + //~^ ERROR couldn't allocate output register for constraint 'd' + } +} diff --git a/src/test/ui/asm/invalid-inline-asm-2.stderr b/src/test/ui/asm/invalid-inline-asm-2.stderr new file mode 100644 index 0000000000000..3534a2ea58c7a --- /dev/null +++ b/src/test/ui/asm/invalid-inline-asm-2.stderr @@ -0,0 +1,8 @@ +error: couldn't allocate output register for constraint 'd' + --> $DIR/invalid-inline-asm-2.rs:7:9 + | +LL | asm!("" : "=d"(a) : : : ); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 16f276ba1ef9d1233efd58d669028ee32d941d2a Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:56:53 +0000 Subject: [PATCH 36/38] Add a test for #26577 --- .../ui/block-expression-remove-semicolon.rs | 10 ++++++++++ .../ui/block-expression-remove-semicolon.stderr | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/block-expression-remove-semicolon.rs create mode 100644 src/test/ui/block-expression-remove-semicolon.stderr diff --git a/src/test/ui/block-expression-remove-semicolon.rs b/src/test/ui/block-expression-remove-semicolon.rs new file mode 100644 index 0000000000000..afa10b38b9144 --- /dev/null +++ b/src/test/ui/block-expression-remove-semicolon.rs @@ -0,0 +1,10 @@ +fn foo() -> i32 { + 0 +} + +fn main() { + let x: i32 = { + //~^ ERROR mismatched types + foo(); //~ HELP consider removing this semicolon + }; +} diff --git a/src/test/ui/block-expression-remove-semicolon.stderr b/src/test/ui/block-expression-remove-semicolon.stderr new file mode 100644 index 0000000000000..aa4889fc5a577 --- /dev/null +++ b/src/test/ui/block-expression-remove-semicolon.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/block-expression-remove-semicolon.rs:6:18 + | +LL | let x: i32 = { + | __________________^ +LL | | //~^ ERROR mismatched types +LL | | foo(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon +LL | | }; + | |_____^ expected i32, found () + | + = note: expected type `i32` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 79c27883eb996feee9aea7e83a6a2a554fbcacc9 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Feb 2019 23:57:08 +0000 Subject: [PATCH 37/38] Add a test for #27054 --- src/test/ui/primitive-binop-lhs-mut.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/test/ui/primitive-binop-lhs-mut.rs diff --git a/src/test/ui/primitive-binop-lhs-mut.rs b/src/test/ui/primitive-binop-lhs-mut.rs new file mode 100644 index 0000000000000..4f1c456ace354 --- /dev/null +++ b/src/test/ui/primitive-binop-lhs-mut.rs @@ -0,0 +1,6 @@ +// run-pass + +fn main() { + let x = Box::new(0); + assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 }); +} From 5ab5747a36a22da403935025e5606145c202157e Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 26 Feb 2019 20:56:52 +0000 Subject: [PATCH 38/38] Update test for issue #55731 --- src/test/ui/issues/issue-55731.stderr | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr index 67f2053de1ebe..f490b45bf9767 100644 --- a/src/test/ui/issues/issue-55731.stderr +++ b/src/test/ui/issues/issue-55731.stderr @@ -4,9 +4,8 @@ error: implementation of `DistributedIteratorMulti` is not general enough LL | multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough | ^^^^^ | - = note: Due to a where-clause on `multi`, - = note: `Map, X>` must implement `DistributedIteratorMulti<&'0 ()>`, for any lifetime `'0` - = note: but `Map, X>` actually implements `DistributedIteratorMulti<&'1 ()>`, for some specific lifetime `'1` + = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0` + = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to previous error