Skip to content

Rollup of 6 pull requests #42130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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