From 256096da9ee680366b839f912e8d3ecccc0da033 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 25 Apr 2018 16:33:02 -0500 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 e5280e452f194ea7b4066c50b7954e07cb054161 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:13:49 -0500 Subject: [PATCH 6/7] 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 f9f992379de4a82637ec4bf717ff42f27872bc48 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:27:17 -0500 Subject: [PATCH 7/7] 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, } }