Skip to content

Commit

Permalink
Auto merge of #42130 - Mark-Simulacrum:rollup, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

- Successful merges: #41892, #42062, #42091, #42093, #42098, #42127
- Failed merges:
  • Loading branch information
bors committed May 21, 2017
2 parents 92ee08a + 382c0eb commit 7ac844f
Show file tree
Hide file tree
Showing 22 changed files with 129 additions and 54 deletions.
7 changes: 7 additions & 0 deletions src/doc/unstable-book/src/library-features/needs-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# `needs_drop`

The tracking issue for this feature is: [#41890]

[#41890]: https://github.com/rust-lang/rust/issues/41890

------------------------
9 changes: 4 additions & 5 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(generic_param_attrs)]
#![feature(needs_drop)]
#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]

Expand Down Expand Up @@ -82,7 +83,7 @@ impl<T> TypedArenaChunk<T> {
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
if intrinsics::needs_drop::<T>() {
if mem::needs_drop::<T>() {
let mut start = self.start();
// Destroy all allocated objects.
for _ in 0..len {
Expand Down Expand Up @@ -350,7 +351,7 @@ impl DroplessArena {
#[inline]
pub fn alloc<T>(&self, object: T) -> &mut T {
unsafe {
assert!(!intrinsics::needs_drop::<T>());
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);

self.align_for::<T>();
Expand Down Expand Up @@ -379,9 +380,7 @@ impl DroplessArena {
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
where T: Copy {
unsafe {
assert!(!intrinsics::needs_drop::<T>());
}
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
self.align_for::<T>();
Expand Down
52 changes: 52 additions & 0 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,58 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}

/// Returns whether dropping values of type `T` matters.
///
/// This is purely an optimization hint, and may be implemented conservatively.
/// For instance, always returning `true` would be a valid implementation of
/// this function.
///
/// Low level implementations of things like collections, which need to manually
/// drop their data, should use this function to avoid unnecessarily
/// trying to drop all their contents when they are destroyed. This might not
/// make a difference in release builds (where a loop that has no side-effects
/// is easily detected and eliminated), but is often a big win for debug builds.
///
/// Note that `ptr::drop_in_place` already performs this check, so if your workload
/// can be reduced to some small number of drop_in_place calls, using this is
/// unnecessary. In particular note that you can drop_in_place a slice, and that
/// will do a single needs_drop check for all the values.
///
/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
/// values one at a time and should use this API.
///
///
/// # Examples
///
/// Here's an example of how a collection might make use of needs_drop:
///
/// ```ignore
/// #![feature(needs_drop)]
/// use std::{mem, ptr};
///
/// pub struct MyCollection<T> { /* ... */ }
///
/// impl<T> Drop for MyCollection<T> {
/// fn drop(&mut self) {
/// unsafe {
/// // drop the data
/// if mem::needs_drop::<T>() {
/// for x in self.iter_mut() {
/// ptr::drop_in_place(x);
/// }
/// }
/// self.free_buffer();
/// }
/// }
/// }
/// ```
#[inline]
#[unstable(feature = "needs_drop", issue = "41890")]
pub fn needs_drop<T>() -> bool {
unsafe { intrinsics::needs_drop::<T>() }
}

/// Creates a value whose bytes are all zero.
///
/// This has the same effect as allocating space with
Expand Down
1 change: 1 addition & 0 deletions src/libcore/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,7 @@ impl<T> AtomicPtr<T> {
}
}

#[cfg(target_has_atomic = "ptr")]
macro_rules! atomic_int {
($stable:meta,
$stable_cxchg:meta,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
heading: &str, span: Span)
-> (String, Option<Span>) {
let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
Some(span))
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ impl<'a> Debug for DiagnosticBuilder<'a> {
}
}

/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
/// we emit a bug.
/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
/// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> {
fn drop(&mut self) {
if !panicking() && !self.cancelled() {
Expand Down
6 changes: 2 additions & 4 deletions src/librustc_errors/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,10 +1296,8 @@ impl Write for BufferedWriter {
}
fn flush(&mut self) -> io::Result<()> {
let mut stderr = io::stderr();
let result = (|| {
stderr.write_all(&self.buffer)?;
stderr.flush()
})();
let result = stderr.write_all(&self.buffer)
.and_then(|_| stderr.flush());
self.buffer.clear();
result
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_errors/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ impl Handler {
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
self.emit(&sp.into(), msg, Fatal);
self.panic_if_treat_err_as_bug();
return FatalError;
FatalError
}
pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
sp: S,
Expand All @@ -392,7 +392,7 @@ impl Handler {
-> FatalError {
self.emit_with_code(&sp.into(), msg, code, Fatal);
self.panic_if_treat_err_as_bug();
return FatalError;
FatalError
}
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Error);
Expand Down
3 changes: 1 addition & 2 deletions src/libstd/collections/hash/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ use alloc::heap::{allocate, deallocate};

use cmp;
use hash::{BuildHasher, Hash, Hasher};
use intrinsics::needs_drop;
use marker;
use mem::{align_of, size_of};
use mem::{align_of, size_of, needs_drop};
use mem;
use ops::{Deref, DerefMut};
use ptr::{self, Unique, Shared};
Expand Down
49 changes: 33 additions & 16 deletions src/libstd/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
//! This module contains functions to inspect various aspects such as
//! environment variables, process arguments, the current directory, and various
//! other important directories.
//!
//! There are several functions and structs in this module that have a
//! counterpart ending in `os`. Those ending in `os` will return an [`OsString`]
//! and those without will be returning a [`String`].
//!
//! [`OsString`]: ../../std/ffi/struct.OsString.html
//! [`String`]: ../string/struct.String.html

#![stable(feature = "env", since = "1.0.0")]

Expand Down Expand Up @@ -74,15 +81,17 @@ pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {

/// An iterator over a snapshot of the environment variables of this process.
///
/// This structure is created through the [`std::env::vars`] function.
/// This structure is created by the [`std::env::vars`] function. See its
/// documentation for more.
///
/// [`std::env::vars`]: fn.vars.html
#[stable(feature = "env", since = "1.0.0")]
pub struct Vars { inner: VarsOs }

/// An iterator over a snapshot of the environment variables of this process.
///
/// This structure is created through the [`std::env::vars_os`] function.
/// This structure is created by the [`std::env::vars_os`] function. See
/// its documentation for more.
///
/// [`std::env::vars_os`]: fn.vars_os.html
#[stable(feature = "env", since = "1.0.0")]
Expand Down Expand Up @@ -176,12 +185,10 @@ impl fmt::Debug for VarsOs {

/// Fetches the environment variable `key` from the current process.
///
/// The returned result is [`Ok(s)`] if the environment variable is present and is
/// valid unicode. If the environment variable is not present, or it is not
/// valid unicode, then [`VarError`] will be returned.
/// # Errors
///
/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok
/// [`VarError`]: enum.VarError.html
/// * Environment variable is not present
/// * Environment variable is not valid unicode
///
/// # Examples
///
Expand Down Expand Up @@ -233,7 +240,8 @@ fn _var_os(key: &OsStr) -> Option<OsString> {
})
}

/// Possible errors from the [`env::var`] function.
/// The error type for operations interacting with environment variables.
/// Possibly returned from the [`env::var`] function.
///
/// [`env::var`]: fn.var.html
#[derive(Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -356,10 +364,13 @@ fn _remove_var(k: &OsStr) {
})
}

/// An iterator over `PathBuf` instances for parsing an environment variable
/// according to platform-specific conventions.
/// An iterator that splits an environment variable into paths according to
/// platform-specific conventions.
///
/// This structure is returned from `std::env::split_paths`.
/// This structure is created by the [`std::env::split_paths`] function See its
/// documentation for more.
///
/// [`std::env::split_paths`]: fn.split_paths.html
#[stable(feature = "env", since = "1.0.0")]
pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }

Expand Down Expand Up @@ -402,8 +413,10 @@ impl<'a> fmt::Debug for SplitPaths<'a> {
}
}

/// Error type returned from `std::env::join_paths` when paths fail to be
/// joined.
/// The error type for operations on the `PATH` variable. Possibly returned from
/// the [`env::join_paths`] function.
///
/// [`env::join_paths`]: fn.join_paths.html
#[derive(Debug)]
#[stable(feature = "env", since = "1.0.0")]
pub struct JoinPathsError {
Expand All @@ -413,7 +426,7 @@ pub struct JoinPathsError {
/// Joins a collection of [`Path`]s appropriately for the `PATH`
/// environment variable.
///
/// Returns an [`OsString`] on success.
/// # Errors
///
/// Returns an [`Err`][err] (containing an error message) if one of the input
/// [`Path`]s contains an invalid character for constructing the `PATH`
Expand Down Expand Up @@ -493,12 +506,16 @@ pub fn home_dir() -> Option<PathBuf> {

/// Returns the path of a temporary directory.
///
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
/// # Unix
///
/// Returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
///
/// On Windows, returns the value of, in order, the `TMP`, `TEMP`,
/// # Windows
///
/// Returns the value of, in order, the `TMP`, `TEMP`,
/// `USERPROFILE` environment variable if any are set and not the empty
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ impl<'a> From<&'a OsStr> for Box<OsStr> {
}

#[stable(feature = "os_string_from_box", since = "1.18.0")]
impl<'a> From<Box<OsStr>> for OsString {
impl From<Box<OsStr>> for OsString {
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
#![feature(linkage)]
#![feature(macro_reexport)]
#![feature(needs_panic_runtime)]
#![feature(needs_drop)]
#![feature(never_type)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,7 @@ impl<'a> From<&'a Path> for Box<Path> {
}

#[stable(feature = "path_buf_from_box", since = "1.18.0")]
impl<'a> From<Box<Path>> for PathBuf {
impl From<Box<Path>> for PathBuf {
fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf()
}
Expand Down
7 changes: 4 additions & 3 deletions src/libstd/sys/redox/fast_thread_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
#![unstable(feature = "thread_local_internals", issue = "0")]

use cell::{Cell, UnsafeCell};
use intrinsics;
use mem;
use ptr;


pub struct Key<T> {
inner: UnsafeCell<Option<T>>,

Expand All @@ -37,7 +38,7 @@ impl<T> Key<T> {

pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
Expand All @@ -46,7 +47,7 @@ impl<T> Key<T> {
}

unsafe fn register_dtor(&self) {
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}

Expand Down
6 changes: 3 additions & 3 deletions src/libstd/sys/unix/fast_thread_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use cell::{Cell, UnsafeCell};
use fmt;
use intrinsics;
use mem;
use ptr;

pub struct Key<T> {
Expand Down Expand Up @@ -44,7 +44,7 @@ impl<T> Key<T> {

pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
Expand All @@ -53,7 +53,7 @@ impl<T> Key<T> {
}

unsafe fn register_dtor(&self) {
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-27942.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
pub trait Resources<'a> {}

pub trait Buffer<'a, R: Resources<'a>> {
//~^ NOTE the lifetime 'a as defined on the trait at 13:0...
//~^ NOTE the lifetime 'a as defined on the trait at 13:1...
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait

fn select(&self) -> BufferViewHandle<R>;
Expand All @@ -22,7 +22,7 @@ pub trait Buffer<'a, R: Resources<'a>> {
//~| ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
//~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
//~| NOTE the anonymous lifetime #1 defined on the method body at 17:5...
}

pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
Expand Down
Loading

0 comments on commit 7ac844f

Please sign in to comment.