From 256096da9ee680366b839f912e8d3ecccc0da033 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 25 Apr 2018 16:33:02 -0500 Subject: [PATCH 01/15] Make Vec::new const --- src/liballoc/raw_vec.rs | 16 ++++++++++++++++ src/liballoc/vec.rs | 2 +- src/libcore/ptr.rs | 5 ++--- src/test/run-pass/vec-const-new.rs | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/vec-const-new.rs diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 7ef0a27fc7258..dc8ad9ee06169 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -68,6 +68,16 @@ impl RawVec { } } + /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. + pub const fn empty_in(a: A) -> Self { + // Unique::empty() doubles as "unallocated" and "zero-sized allocation" + RawVec { + ptr: Unique::empty(), + cap: 0, + a, + } + } + /// Like `with_capacity` but parameterized over the choice of /// allocator for the returned RawVec. #[inline] @@ -124,6 +134,12 @@ impl RawVec { Self::new_in(Global) } + /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without + /// allocating. + pub fn empty() -> Self { + Self::empty_in(Global) + } + /// Creates a RawVec (on the system heap) with exactly the /// capacity and alignment requirements for a `[T; cap]`. This is /// equivalent to calling RawVec::new when `cap` is 0 or T is diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b184404c15bfd..757606607bbcf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -324,7 +324,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Vec { Vec { - buf: RawVec::new(), + buf: RawVec::empty(), len: 0, } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 74bb264cc679c..b612a278a34a7 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2551,10 +2551,9 @@ impl Unique { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. // FIXME: rename to dangling() to match NonNull? - pub fn empty() -> Self { + pub const fn empty() -> Self { unsafe { - let ptr = mem::align_of::() as *mut T; - Unique::new_unchecked(ptr) + Unique::new_unchecked(mem::align_of::() as *mut T) } } } diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/vec-const-new.rs new file mode 100644 index 0000000000000..02d8cfdcf988d --- /dev/null +++ b/src/test/run-pass/vec-const-new.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that Vec::new() can be used for constants + +const MY_VEC: Vec = Vec::new(); + +pub fn main() {} From a2105b8e21a71f513e6840ec0571cad5c1a36012 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 25 Apr 2018 16:42:57 -0500 Subject: [PATCH 02/15] make RawVec::empty const --- src/liballoc/raw_vec.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index dc8ad9ee06169..fe18979fb51c7 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -54,6 +54,7 @@ pub struct RawVec { } impl RawVec { + // FIXME: this should be made `const` when `if` statements are allowed /// Like `new` but parameterized over the choice of allocator for /// the returned RawVec. pub fn new_in(a: A) -> Self { @@ -68,6 +69,7 @@ impl RawVec { } } + // FIXME: this should removed when `new_in` can be made `const` /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. pub const fn empty_in(a: A) -> Self { // Unique::empty() doubles as "unallocated" and "zero-sized allocation" @@ -134,9 +136,10 @@ impl RawVec { Self::new_in(Global) } + // FIXME: this should removed when `new` can be made `const` /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without /// allocating. - pub fn empty() -> Self { + pub const fn empty() -> Self { Self::empty_in(Global) } From 20ef0e001a1620436073d01f43a4a462d1967902 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 26 Apr 2018 12:46:28 -0500 Subject: [PATCH 03/15] make Vec::new const :P --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 757606607bbcf..1d95f76fd7732 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -322,7 +322,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Vec { + pub const fn new() -> Vec { Vec { buf: RawVec::empty(), len: 0, From c122b3a42c5dd57682be353cb9433241f67ab9cb Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 26 Apr 2018 22:38:39 -0500 Subject: [PATCH 04/15] not insta-stable --- src/liballoc/lib.rs | 1 + src/liballoc/vec.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6399be98cd519..c495078626595 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -123,6 +123,7 @@ #![feature(pointer_methods)] #![feature(inclusive_range_fields)] #![cfg_attr(stage0, feature(generic_param_attrs))] +#![feature(rustc_const_unstable)] #![cfg_attr(not(test), feature(fn_traits, i128))] #![cfg_attr(test, feature(test))] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 1d95f76fd7732..415d75664ff4a 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -322,6 +322,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_new")] pub const fn new() -> Vec { Vec { buf: RawVec::empty(), From 0212e0230a500c3b50a6830a20c12d1db3520b99 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 28 Apr 2018 20:59:25 -0500 Subject: [PATCH 05/15] feature on test --- src/test/run-pass/vec-const-new.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/vec-const-new.rs index 02d8cfdcf988d..62e2a36d7cc77 100644 --- a/src/test/run-pass/vec-const-new.rs +++ b/src/test/run-pass/vec-const-new.rs @@ -10,6 +10,8 @@ // Test that Vec::new() can be used for constants +#![feature(const_vec_new)] + const MY_VEC: Vec = Vec::new(); pub fn main() {} From 368fe37c226c6e067ba4fa93cab0bbd5b1c09e6c Mon Sep 17 00:00:00 2001 From: Pazzaz Date: Sun, 29 Apr 2018 13:45:33 +0200 Subject: [PATCH 06/15] Add more links in panic docs --- src/libstd/panic.rs | 51 ++++++++++++++++++++++++++--------------- src/libstd/panicking.rs | 8 ++++++- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 28c178307a510..229034eb7790b 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -31,10 +31,14 @@ pub use core::panic::{PanicInfo, Location}; /// A marker trait which represents "panic safe" types in Rust. /// /// This trait is implemented by default for many types and behaves similarly in -/// terms of inference of implementation to the `Send` and `Sync` traits. The -/// purpose of this trait is to encode what types are safe to cross a `catch_unwind` +/// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The +/// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`] /// boundary with no fear of unwind safety. /// +/// [`Send`]: ../marker/trait.Send.html +/// [`Sync`]: ../marker/trait.Sync.html +/// [`catch_unwind`]: ./fn.catch_unwind.html +/// /// ## What is unwind safety? /// /// In Rust a function can "return" early if it either panics or calls a @@ -95,12 +99,13 @@ pub use core::panic::{PanicInfo, Location}; /// /// ## When should `UnwindSafe` be used? /// -/// Is not intended that most types or functions need to worry about this trait. -/// It is only used as a bound on the `catch_unwind` function and as mentioned above, -/// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe` -/// wrapper struct in this module can be used to force this trait to be -/// implemented for any closed over variables passed to the `catch_unwind` function -/// (more on this below). +/// It is not intended that most types or functions need to worry about this trait. +/// It is only used as a bound on the `catch_unwind` function and as mentioned +/// above, the lack of `unsafe` means it is mostly an advisory. The +/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be +/// implemented for any closed over variables passed to `catch_unwind`. +/// +/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \ across an unwind boundary"] @@ -109,11 +114,14 @@ pub auto trait UnwindSafe {} /// A marker trait representing types where a shared reference is considered /// unwind safe. /// -/// This trait is namely not implemented by `UnsafeCell`, the root of all +/// This trait is namely not implemented by [`UnsafeCell`], the root of all /// interior mutability. /// /// This is a "helper marker trait" used to provide impl blocks for the -/// `UnwindSafe` trait, for more information see that documentation. +/// [`UnwindSafe`] trait, for more information see that documentation. +/// +/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html +/// [`UnwindSafe`]: ./trait.UnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may contain interior mutability \ and a reference may not be safely transferrable \ @@ -122,14 +130,15 @@ pub auto trait RefUnwindSafe {} /// A simple wrapper around a type to assert that it is unwind safe. /// -/// When using `catch_unwind` it may be the case that some of the closed over +/// When using [`catch_unwind`] it may be the case that some of the closed over /// variables are not unwind safe. For example if `&mut T` is captured the /// compiler will generate a warning indicating that it is not unwind safe. It /// may not be the case, however, that this is actually a problem due to the -/// specific usage of `catch_unwind` if unwind safety is specifically taken into +/// specific usage of [`catch_unwind`] if unwind safety is specifically taken into /// account. This wrapper struct is useful for a quick and lightweight /// annotation that a variable is indeed unwind safe. /// +/// [`catch_unwind`]: ./fn.catch_unwind.html /// # Examples /// /// One way to use `AssertUnwindSafe` is to assert that the entire closure @@ -318,18 +327,22 @@ impl fmt::Debug for AssertUnwindSafe { /// panic and allowing a graceful handling of the error. /// /// It is **not** recommended to use this function for a general try/catch -/// mechanism. The `Result` type is more appropriate to use for functions that +/// mechanism. The [`Result`] type is more appropriate to use for functions that /// can fail on a regular basis. Additionally, this function is not guaranteed /// to catch all panics, see the "Notes" section below. /// -/// The closure provided is required to adhere to the `UnwindSafe` trait to ensure +/// [`Result`]: ../result/enum.Result.html +/// +/// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure /// that all captured variables are safe to cross this boundary. The purpose of /// this bound is to encode the concept of [exception safety][rfc] in the type /// system. Most usage of this function should not need to worry about this /// bound as programs are naturally unwind safe without `unsafe` code. If it -/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this -/// module can be used to quickly assert that the usage here is indeed unwind -/// safe. +/// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly +/// assert that the usage here is indeed unwind safe. +/// +/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html +/// [`UnwindSafe`]: ./trait.UnwindSafe.html /// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md /// @@ -364,9 +377,11 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// Triggers a panic without invoking the panic hook. /// -/// This is designed to be used in conjunction with `catch_unwind` to, for +/// This is designed to be used in conjunction with [`catch_unwind`] to, for /// example, carry a panic across a layer of C code. /// +/// [`catch_unwind`]: ./fn.catch_unwind.html +/// /// # Notes /// /// Note that panics in Rust are not always implemented via unwinding, but they diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 24eae6a4c821e..403056240bf57 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -76,7 +76,9 @@ static mut HOOK: Hook = Hook::Default; /// is invoked. As such, the hook will run with both the aborting and unwinding /// runtimes. The default hook prints a message to standard error and generates /// a backtrace if requested, but this behavior can be customized with the -/// `set_hook` and `take_hook` functions. +/// `set_hook` and [`take_hook`] functions. +/// +/// [`take_hook`]: ./fn.take_hook.html /// /// The hook is provided with a `PanicInfo` struct which contains information /// about the origin of the panic, including the payload passed to `panic!` and @@ -121,6 +123,10 @@ pub fn set_hook(hook: Box) { /// Unregisters the current panic hook, returning it. /// +/// *See also the function [`set_hook`].* +/// +/// [`set_hook`]: ./fn.set_hook.html +/// /// If no custom hook is registered, the default hook will be returned. /// /// # Panics From 269d2790946858dd1b504c21c54a267ac63dc15a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 29 Apr 2018 10:15:40 -0700 Subject: [PATCH 07/15] Fix some broken links in docs. --- src/libcore/iter/iterator.rs | 2 ++ src/libcore/marker.rs | 2 ++ src/libstd/collections/hash/table.rs | 2 +- src/libstd/ffi/c_str.rs | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 6a77de2c9868d..b27bd3142e1ed 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1094,6 +1094,8 @@ pub trait Iterator { /// `flatten()` a three-dimensional array the result will be /// two-dimensional and not one-dimensional. To get a one-dimensional /// structure, you have to `flatten()` again. + /// + /// [`flat_map()`]: #method.flat_map #[inline] #[unstable(feature = "iterator_flatten", issue = "48213")] fn flatten(self) -> Flatten diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index feb689dbc1fe8..c074adfd570e3 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -602,6 +602,8 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// `Pin` pointer. /// /// This trait is automatically implemented for almost every type. +/// +/// [`Pin`]: ../mem/struct.Pin.html #[unstable(feature = "pin", issue = "49150")] pub unsafe auto trait Unpin {} diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 52c53dc3b1251..b50652ed6b557 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -79,7 +79,7 @@ impl TaggedHashUintPtr { /// /// Essential invariants of this structure: /// -/// - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw` +/// - if `t.hashes[i] == EMPTY_BUCKET`, then `Bucket::at_index(&t, i).raw` /// points to 'undefined' contents. Don't read from it. This invariant is /// enforced outside this module with the `EmptyBucket`, `FullBucket`, /// and `SafeHash` types. diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index c88c2bc913713..8164f52d3c34d 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1118,6 +1118,7 @@ impl CStr { /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed + /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned /// [`str`]: ../primitive.str.html /// [`String`]: ../string/struct.String.html /// From e5280e452f194ea7b4066c50b7954e07cb054161 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:13:49 -0500 Subject: [PATCH 08/15] use const trick --- src/liballoc/raw_vec.rs | 29 ++++++----------------------- src/liballoc/vec.rs | 2 +- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index fe18979fb51c7..6ca668fda59fb 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -54,28 +54,18 @@ pub struct RawVec { } impl RawVec { - // FIXME: this should be made `const` when `if` statements are allowed /// Like `new` but parameterized over the choice of allocator for /// the returned RawVec. - pub fn new_in(a: A) -> Self { + pub const fn new_in(a: A) -> Self { // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + // FIXME(mark-i-m): use this line when `if`s are allowed in `const` + //let cap = if mem::size_of::() == 0 { !0 } else { 0 }; // Unique::empty() doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::empty(), - cap, - a, - } - } - - // FIXME: this should removed when `new_in` can be made `const` - /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. - pub const fn empty_in(a: A) -> Self { - // Unique::empty() doubles as "unallocated" and "zero-sized allocation" - RawVec { - ptr: Unique::empty(), - cap: 0, + // FIXME(mark-i-m): use `cap` when ifs are allowed in const + cap: [0, !0][(mem::size_of::() != 0) as usize], a, } } @@ -132,17 +122,10 @@ impl RawVec { /// RawVec with capacity 0. If T has 0 size, then it makes a /// RawVec with capacity `usize::MAX`. Useful for implementing /// delayed allocation. - pub fn new() -> Self { + pub const fn new() -> Self { Self::new_in(Global) } - // FIXME: this should removed when `new` can be made `const` - /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without - /// allocating. - pub const fn empty() -> Self { - Self::empty_in(Global) - } - /// Creates a RawVec (on the system heap) with exactly the /// capacity and alignment requirements for a `[T; cap]`. This is /// equivalent to calling RawVec::new when `cap` is 0 or T is diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 415d75664ff4a..35d0a69a05abe 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -325,7 +325,7 @@ impl Vec { #[rustc_const_unstable(feature = "const_vec_new")] pub const fn new() -> Vec { Vec { - buf: RawVec::empty(), + buf: RawVec::new(), len: 0, } } From 0a6e91bdbc6368a15bd5ccc632954b8247284b6d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 30 Apr 2018 01:13:54 +0300 Subject: [PATCH 09/15] Add a few more tests for proc macro feature gating --- .../proc-macro/proc-macro-gates.rs | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs index 0dc1c2ab2daf9..fff433b90ce69 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs @@ -24,9 +24,17 @@ use foo::*; #[foo::a] //~ ERROR: paths of length greater than one fn _test() {} +fn _test_inner() { + #![a] // OK +} + #[a] //~ ERROR: custom attributes cannot be applied to modules mod _test2 {} +mod _test2_inner { + #![a] //~ ERROR: custom attributes cannot be applied to modules +} + #[a = y] //~ ERROR: must only be followed by a delimiter token fn _test3() {} @@ -36,19 +44,40 @@ fn _test4() {} #[a () = ] //~ ERROR: must only be followed by a delimiter token fn _test5() {} -fn main() { +fn attrs() { + // Statement, item + #[a] // OK + struct S; + + // Statement, macro + #[a] //~ ERROR: custom attributes cannot be applied to statements + println!(); + + // Statement, semi + #[a] //~ ERROR: custom attributes cannot be applied to statements + S; + + // Statement, local #[a] //~ ERROR: custom attributes cannot be applied to statements let _x = 2; - let _x = #[a] 2; - //~^ ERROR: custom attributes cannot be applied to expressions - - let _x: m!(u32) = 3; - //~^ ERROR: procedural macros cannot be expanded to types - if let m!(Some(_x)) = Some(3) { - //~^ ERROR: procedural macros cannot be expanded to patterns - } - let _x = m!(3); - //~^ ERROR: procedural macros cannot be expanded to expressions - m!(let _x = 3;); - //~^ ERROR: procedural macros cannot be expanded to statements + + // Expr + let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions + + // Opt expr + let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions + + // Expr macro + let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions +} + +fn main() { + let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types + if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns + + m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements + m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements + + let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions + let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions } From f9f992379de4a82637ec4bf717ff42f27872bc48 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:27:17 -0500 Subject: [PATCH 10/15] heh, logic is hard --- src/liballoc/raw_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 6ca668fda59fb..eb25ae1751170 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -65,7 +65,7 @@ impl RawVec { RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const - cap: [0, !0][(mem::size_of::() != 0) as usize], + cap: [0, !0][(mem::size_of::() == 0) as usize], a, } } From cc53db8bf9f7583b14ae3a309fb65c3cb676bd66 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 00:40:11 +0100 Subject: [PATCH 11/15] Correct unused field warning on &struct match --- src/librustc/middle/liveness.rs | 28 +++++++++++++------ ...47390-unused-variable-in-struct-pattern.rs | 12 ++++++++ ...0-unused-variable-in-struct-pattern.stderr | 14 +++++++--- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 17c114bc3b3c0..bf7fecb884ebf 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -412,18 +412,28 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { } fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { - for pat in &arm.pats { - // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`) + for mut pat in &arm.pats { + // For struct patterns, take note of which fields used shorthand + // (`x` rather than `x: x`). // - // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased - // out in favor of `HirId`s; however, we need to match the signature of `each_binding`, - // which uses `NodeIds`. + // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be + // phased out in favor of `HirId`s; however, we need to match the signature of + // `each_binding`, which uses `NodeIds`. let mut shorthand_field_ids = NodeSet(); - if let hir::PatKind::Struct(_, ref fields, _) = pat.node { - for field in fields { - if field.node.is_shorthand { - shorthand_field_ids.insert(field.node.pat.id); + loop { + match pat.node { + hir::PatKind::Struct(_, ref fields, _) => { + for field in fields { + if field.node.is_shorthand { + shorthand_field_ids.insert(field.node.pat.id); + } + } + break; + } + hir::PatKind::Ref(ref deref_pat, _) => { + pat = deref_pat; } + _ => break } } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 18b83370355b6..498e7e5e6c4c6 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -18,6 +18,10 @@ struct SoulHistory { endless_and_singing: bool } +enum Large { + Suit { case: () } +} + fn main() { let i_think_continually = 2; let who_from_the_womb_remembered = SoulHistory { @@ -31,4 +35,12 @@ fn main() { endless_and_singing: true } = who_from_the_womb_remembered { hours_are_suns = false; } + + let bag = &Large::Suit { + case: () + }; + + match bag { + &Large::Suit { case } => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index 35fe5479406df..cecda22280c05 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,5 +1,5 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead @@ -12,13 +12,13 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:34:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -38,3 +38,9 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_assignments)] implied by #[warn(unused)] +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:24 + | +LL | &Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + From 8e8fe9042c86c53d90ce17cc0754505bf014d0ed Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 00:51:02 +0100 Subject: [PATCH 12/15] Correct unused field warning on box struct match --- src/librustc/middle/liveness.rs | 5 +++-- ...47390-unused-variable-in-struct-pattern.rs | 10 ++++++++-- ...0-unused-variable-in-struct-pattern.stderr | 20 ++++++++++++------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index bf7fecb884ebf..b32ee2f29d22e 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -430,8 +430,9 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { } break; } - hir::PatKind::Ref(ref deref_pat, _) => { - pat = deref_pat; + hir::PatKind::Ref(ref inner_pat, _) | + hir::PatKind::Box(ref inner_pat) => { + pat = inner_pat; } _ => break } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 498e7e5e6c4c6..db3c812f259c0 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -10,6 +10,8 @@ // compile-pass +#![feature(box_syntax)] +#![feature(box_patterns)] #![warn(unused)] // UI tests pass `-A unused` (#43896) struct SoulHistory { @@ -36,11 +38,15 @@ fn main() { hours_are_suns = false; } - let bag = &Large::Suit { + let bag = Large::Suit { case: () }; - match bag { + match &bag { &Large::Suit { case } => {} }; + + match box bag { + box Large::Suit { case } => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index cecda22280c05..ce064f9c93fc3 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,24 +1,24 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:28:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead | note: lint level defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9 | LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:34:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,21 +26,27 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9 | LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_assignments)] implied by #[warn(unused)] warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:27 + | +LL | box Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + From 2eb8343af18470d3c48a50c68dbaeb1887b42c37 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 01:27:37 +0100 Subject: [PATCH 13/15] Correct unused field warning on struct match container patterns --- src/librustc/middle/liveness.rs | 29 +++++++++++---- ...47390-unused-variable-in-struct-pattern.rs | 25 +++++++++++++ ...0-unused-variable-in-struct-pattern.stderr | 36 +++++++++++++++---- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b32ee2f29d22e..d1a46f5f15563 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -111,6 +111,7 @@ use ty::{self, TyCtxt}; use lint; use util::nodemap::{NodeMap, NodeSet}; +use std::collections::VecDeque; use std::{fmt, usize}; use std::io::prelude::*; use std::io; @@ -420,21 +421,35 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { // phased out in favor of `HirId`s; however, we need to match the signature of // `each_binding`, which uses `NodeIds`. let mut shorthand_field_ids = NodeSet(); - loop { + let mut pats = VecDeque::new(); + pats.push_back(pat); + while let Some(pat) = pats.pop_front() { + use hir::PatKind::*; match pat.node { - hir::PatKind::Struct(_, ref fields, _) => { + Binding(_, _, _, ref inner_pat) => { + pats.extend(inner_pat.iter()); + } + Struct(_, ref fields, _) => { for field in fields { if field.node.is_shorthand { shorthand_field_ids.insert(field.node.pat.id); } } - break; } - hir::PatKind::Ref(ref inner_pat, _) | - hir::PatKind::Box(ref inner_pat) => { - pat = inner_pat; + Ref(ref inner_pat, _) | + Box(ref inner_pat) => { + pats.push_back(inner_pat); + } + TupleStruct(_, ref inner_pats, _) | + Tuple(ref inner_pats, _) => { + pats.extend(inner_pats.iter()); + } + Slice(ref pre_pats, ref inner_pat, ref post_pats) => { + pats.extend(pre_pats.iter()); + pats.extend(inner_pat.iter()); + pats.extend(post_pats.iter()); } - _ => break + _ => {} } } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index db3c812f259c0..6994a377a06d7 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -20,10 +20,13 @@ struct SoulHistory { endless_and_singing: bool } +#[derive(Clone, Copy)] enum Large { Suit { case: () } } +struct Tuple(Large, ()); + fn main() { let i_think_continually = 2; let who_from_the_womb_remembered = SoulHistory { @@ -42,11 +45,33 @@ fn main() { case: () }; + // Plain struct + match bag { + Large::Suit { case } => {} + }; + + // Referenced struct match &bag { &Large::Suit { case } => {} }; + // Boxed struct match box bag { box Large::Suit { case } => {} }; + + // Tuple with struct + match (bag,) { + (Large::Suit { case },) => {} + }; + + // Slice with struct + match [bag] { + [Large::Suit { case }] => {} + }; + + // Tuple struct with struct + match Tuple(bag, ()) { + Tuple(Large::Suit { case }, ()) => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index ce064f9c93fc3..7bfe2c9162ed1 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,5 +1,5 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:28:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:31:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead @@ -12,13 +12,13 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -39,14 +39,38 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_assignments)] implied by #[warn(unused)] warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23 + | +LL | Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:27 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27 | LL | box Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24 + | +LL | (Large::Suit { case },) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24 + | +LL | [Large::Suit { case }] => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29 + | +LL | Tuple(Large::Suit { case }, ()) => {} + | ^^^^ help: try ignoring the field: `case: _` + From bd4ebf28bdf6eb898971b194f5cf773c88281251 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 30 Apr 2018 07:43:22 +0200 Subject: [PATCH 14/15] check that #[used] is used only on statics --- src/librustc/hir/check_attr.rs | 12 ++++++++++++ src/test/compile-fail/used.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/compile-fail/used.rs diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 19f8d15662d84..cad6ff8ae9fc2 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -31,6 +31,7 @@ enum Target { Expression, Statement, Closure, + Static, Other, } @@ -43,6 +44,7 @@ impl Target { hir::ItemEnum(..) => Target::Enum, hir::ItemConst(..) => Target::Const, hir::ItemForeignMod(..) => Target::ForeignMod, + hir::ItemStatic(..) => Target::Static, _ => Target::Other, } } @@ -102,6 +104,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } self.check_repr(item, target); + self.check_used(item, target); } /// Check if an `#[inline]` is applied to a function or a closure. @@ -305,6 +308,15 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } } } + + fn check_used(&self, item: &hir::Item, target: Target) { + for attr in &item.attrs { + if attr.name().map(|name| name == "used").unwrap_or(false) && target != Target::Static { + self.tcx.sess + .span_err(attr.span, "attribute must be applied to a `static` variable"); + } + } + } } impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { diff --git a/src/test/compile-fail/used.rs b/src/test/compile-fail/used.rs new file mode 100644 index 0000000000000..f170d9c25f56d --- /dev/null +++ b/src/test/compile-fail/used.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(used)] + +#[used] +static FOO: u32 = 0; // OK + +#[used] //~ ERROR attribute must be applied to a `static` variable +fn foo() {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +struct Foo {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +trait Bar {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +impl Bar for Foo {} + +fn main() {} From 21941c8129da7b37f5df687e3862a5b331c04f83 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 30 Apr 2018 17:04:42 +0200 Subject: [PATCH 15/15] Update Cargo to 2018-04-28 122fd5be5201913d42e219e132d6569493583bca --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 0a1add2d8689a..122fd5be52019 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80 +Subproject commit 122fd5be5201913d42e219e132d6569493583bca