Skip to content

Commit

Permalink
Auto merge of #41237 - frewsxcv:rollup, r=frewsxcv
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

- Successful merges: #40377, #40559, #41173, #41202, #41204, #41209, #41216, #41231
- Failed merges:
  • Loading branch information
bors committed Apr 12, 2017
2 parents f8107c0 + 72538de commit da32752
Show file tree
Hide file tree
Showing 33 changed files with 399 additions and 131 deletions.
2 changes: 1 addition & 1 deletion src/bootstrap/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub fn llvm(build: &Build, target: &str) {
}

if env::var_os("SCCACHE_ERROR_LOG").is_some() {
cfg.env("RUST_LOG", "sccache=debug");
cfg.env("RUST_LOG", "sccache=info");
}

// FIXME: we don't actually need to build all LLVM tools and all LLVM
Expand Down
1 change: 0 additions & 1 deletion src/ci/docker/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ if [ "$SCCACHE_BUCKET" != "" ]; then
args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
args="$args --env SCCACHE_ERROR_LOG=/tmp/sccache/sccache.log"
args="$args --env SCCACHE_LOG_LEVEL=debug"
args="$args --volume $objdir/tmp:/tmp/sccache"
else
mkdir -p $HOME/.cache/sccache
Expand Down
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
- [loop_break_value](loop-break-value.md)
- [macro_reexport](macro-reexport.md)
- [main](main.md)
- [manually_drop](manually-drop.md)
- [map_entry_recover_keys](map-entry-recover-keys.md)
- [mpsc_select](mpsc-select.md)
- [n16](n16.md)
Expand Down
Empty file.
1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#![feature(heap_api)]
#![feature(inclusive_range)]
#![feature(lang_items)]
#![feature(manually_drop)]
#![feature(nonzero)]
#![feature(pattern)]
#![feature(placement_in)]
Expand Down
12 changes: 3 additions & 9 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,7 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
// performance than with the 2nd method.
//
// All methods were benchmarked, and the 3rd showed best results. So we chose that one.
let mut tmp = NoDrop { value: ptr::read(&v[0]) };
let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));

// Intermediate state of the insertion process is always tracked by `hole`, which
// serves two purposes:
Expand All @@ -1571,13 +1571,13 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
// initially held exactly once.
let mut hole = InsertionHole {
src: &mut tmp.value,
src: &mut *tmp,
dest: &mut v[1],
};
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);

for i in 2..v.len() {
if !is_less(&v[i], &tmp.value) {
if !is_less(&v[i], &*tmp) {
break;
}
ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
Expand All @@ -1587,12 +1587,6 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
}
}

// Holds a value, but never drops it.
#[allow(unions_with_drop_fields)]
union NoDrop<T> {
value: T
}

// When dropped, copies from `src` into `dest`.
struct InsertionHole<T> {
src: *mut T,
Expand Down
3 changes: 0 additions & 3 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,6 @@ extern "rust-intrinsic" {
/// initialize memory previous set to the result of `uninit`.
pub fn uninit<T>() -> T;

/// Moves a value out of scope without running drop glue.
pub fn forget<T>(_: T) -> ();

/// Reinterprets the bits of a value of one type as another type.
///
/// Both types must have the same size. Neither the original, nor the result,
Expand Down
8 changes: 6 additions & 2 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1532,14 +1532,18 @@ pub trait Iterator {
/// Stopping at the first `true`:
///
/// ```
/// let a = [1, 2, 3];
/// let a = [1, 2, 3, 4];
///
/// let mut iter = a.iter();
///
/// assert_eq!(iter.position(|&x| x == 2), Some(1));
/// assert_eq!(iter.position(|&x| x >= 2), Some(1));
///
/// // we can still use `iter`, as there are more elements.
/// assert_eq!(iter.next(), Some(&3));
///
/// // The returned index depends on iterator state
/// assert_eq!(iter.position(|&x| x == 4), Some(0));
///
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
120 changes: 119 additions & 1 deletion src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub use intrinsics::transmute;
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn forget<T>(t: T) {
unsafe { intrinsics::forget(t) }
ManuallyDrop::new(t);
}

/// Returns the size of a type in bytes.
Expand Down Expand Up @@ -736,3 +736,121 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
}
}


/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// the type:
///
/// ```rust
/// # #![feature(manually_drop)]
/// use std::mem::ManuallyDrop;
/// struct Peach;
/// struct Banana;
/// struct Melon;
/// struct FruitBox {
/// // Immediately clear there’s something non-trivial going on with these fields.
/// peach: ManuallyDrop<Peach>,
/// melon: Melon, // Field that’s independent of the other two.
/// banana: ManuallyDrop<Banana>,
/// }
///
/// impl Drop for FruitBox {
/// fn drop(&mut self) {
/// unsafe {
/// // Explicit ordering in which field destructors are run specified in the intuitive
/// // location – the destructor of the structure containing the fields.
/// // Moreover, one can now reorder fields within the struct however much they want.
/// ManuallyDrop::drop(&mut self.peach);
/// ManuallyDrop::drop(&mut self.banana);
/// }
/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
/// }
/// }
/// ```
#[unstable(feature = "manually_drop", issue = "40673")]
#[allow(unions_with_drop_fields)]
pub union ManuallyDrop<T>{ value: T }

impl<T> ManuallyDrop<T> {
/// Wrap a value to be manually dropped.
///
/// # Examples
///
/// ```rust
/// # #![feature(manually_drop)]
/// use std::mem::ManuallyDrop;
/// ManuallyDrop::new(Box::new(()));
/// ```
#[unstable(feature = "manually_drop", issue = "40673")]
#[inline]
pub fn new(value: T) -> ManuallyDrop<T> {
ManuallyDrop { value: value }
}

/// Extract the value from the ManuallyDrop container.
///
/// # Examples
///
/// ```rust
/// # #![feature(manually_drop)]
/// use std::mem::ManuallyDrop;
/// let x = ManuallyDrop::new(Box::new(()));
/// let _: Box<()> = ManuallyDrop::into_inner(x);
/// ```
#[unstable(feature = "manually_drop", issue = "40673")]
#[inline]
pub fn into_inner(slot: ManuallyDrop<T>) -> T {
unsafe {
slot.value
}
}

/// Manually drops the contained value.
///
/// # Unsafety
///
/// This function runs the destructor of the contained value and thus the wrapped value
/// now represents uninitialized data. It is up to the user of this method to ensure the
/// uninitialized data is not actually used.
#[unstable(feature = "manually_drop", issue = "40673")]
#[inline]
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
ptr::drop_in_place(&mut slot.value)
}
}

#[unstable(feature = "manually_drop", issue = "40673")]
impl<T> ::ops::Deref for ManuallyDrop<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
&self.value
}
}
}

#[unstable(feature = "manually_drop", issue = "40673")]
impl<T> ::ops::DerefMut for ManuallyDrop<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
&mut self.value
}
}
}

#[unstable(feature = "manually_drop", issue = "40673")]
impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
unsafe {
fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
}
}
}
30 changes: 12 additions & 18 deletions src/libcore/slice/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ use cmp;
use mem;
use ptr;

/// Holds a value, but never drops it.
#[allow(unions_with_drop_fields)]
union NoDrop<T> {
value: T
}

/// When dropped, copies from `src` into `dest`.
struct CopyOnDrop<T> {
src: *mut T,
Expand All @@ -49,15 +43,15 @@ fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
// Read the first element into a stack-allocated variable. If a following comparison
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) };
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
let mut hole = CopyOnDrop {
src: &mut tmp.value,
src: &mut *tmp,
dest: v.get_unchecked_mut(1),
};
ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);

for i in 2..len {
if !is_less(v.get_unchecked(i), &tmp.value) {
if !is_less(v.get_unchecked(i), &*tmp) {
break;
}

Expand All @@ -81,15 +75,15 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
// Read the last element into a stack-allocated variable. If a following comparison
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) };
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
let mut hole = CopyOnDrop {
src: &mut tmp.value,
src: &mut *tmp,
dest: v.get_unchecked_mut(len - 2),
};
ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);

for i in (0..len-2).rev() {
if !is_less(&tmp.value, v.get_unchecked(i)) {
if !is_less(&*tmp, v.get_unchecked(i)) {
break;
}

Expand Down Expand Up @@ -403,12 +397,12 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)

// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop {
src: unsafe { &mut tmp.value },
src: &mut *tmp,
dest: pivot,
};
let pivot = unsafe { &tmp.value };
let pivot = &*tmp;

// Find the first pair of out-of-order elements.
let mut l = 0;
Expand Down Expand Up @@ -452,12 +446,12 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize

// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } };
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop {
src: unsafe { &mut tmp.value },
src: &mut *tmp,
dest: pivot,
};
let pivot = unsafe { &tmp.value };
let pivot = &*tmp;

// Now partition the slice.
let mut l = 0;
Expand Down
24 changes: 24 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ macro_rules! options {
Some("one of: `address`, `leak`, `memory` or `thread`");
pub const parse_linker_flavor: Option<&'static str> =
Some(::rustc_back::LinkerFlavor::one_of());
pub const parse_optimization_fuel: Option<&'static str> =
Some("crate=integer");
}

#[allow(dead_code)]
Expand Down Expand Up @@ -787,6 +789,21 @@ macro_rules! options {
}
true
}

fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
match v {
None => false,
Some(s) => {
let parts = s.split('=').collect::<Vec<_>>();
if parts.len() != 2 { return false; }
let crate_name = parts[0].to_string();
let fuel = parts[1].parse::<u64>();
if fuel.is_err() { return false; }
*slot = Some((crate_name, fuel.unwrap()));
true
}
}
}
}
) }

Expand Down Expand Up @@ -991,6 +1008,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"Use a sanitizer"),
linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
"Linker flavor"),
fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
"Set the optimization fuel quota for a crate."),
print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
"Make Rustc print the total optimization fuel used by a crate."),
}

pub fn default_lib_output() -> CrateType {
Expand Down Expand Up @@ -1784,11 +1805,13 @@ mod dep_tracking {

impl_dep_tracking_hash_via_hash!(bool);
impl_dep_tracking_hash_via_hash!(usize);
impl_dep_tracking_hash_via_hash!(u64);
impl_dep_tracking_hash_via_hash!(String);
impl_dep_tracking_hash_via_hash!(lint::Level);
impl_dep_tracking_hash_via_hash!(Option<bool>);
impl_dep_tracking_hash_via_hash!(Option<usize>);
impl_dep_tracking_hash_via_hash!(Option<String>);
impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
Expand All @@ -1810,6 +1833,7 @@ mod dep_tracking {
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
Option<cstore::NativeLibraryKind>));
impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
impl DepTrackingHash for SearchPaths {
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
let mut elems: Vec<_> = self
Expand Down
Loading

0 comments on commit da32752

Please sign in to comment.