Skip to content
Permalink
Browse files

Auto merge of #58016 - Centril:rollup, r=Centril

Rollup of 12 pull requests

Successful merges:

 - #57008 (suggest `|` when `,` founds in invalid match value)
 - #57106 (Mark str::trim.* functions as #[must_use].)
 - #57920 (use `SOURCE_DATE_EPOCH` for man page time if set)
 - #57934 (Introduce into_raw_non_null on Rc and Arc)
 - #57971 (SGX target: improve panic & exit handling)
 - #57980 (Add the edition guide to the bookshelf)
 - #57984 (Improve bug message in check_ty)
 - #57999 (Add MOVBE x86 CPU feature)
 - #58000 (Fixes and cleanups)
 - #58005 (update docs for fix_start/end_matches)
 - #58007 (Don't panic when accessing enum variant ctor using `Self` in match)
 - #58008 (Pass correct arguments to places_conflict)

Failed merges:

r? @ghost
  • Loading branch information...
bors committed Jan 31, 2019
2 parents 147311c + 877dee7 commit f40aaa68278ef0879af5fe7ce077c64c6515ea05
@@ -23,7 +23,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::compile;
use crate::tool::{self, Tool};
use crate::cache::{INTERNER, Interned};
use time;
use time::{self, Timespec};

pub fn pkgname(builder: &Builder, component: &str) -> String {
if component == "cargo" {
@@ -528,7 +528,19 @@ impl Step for Rustc {
t!(fs::create_dir_all(image.join("share/man/man1")));
let man_src = builder.src.join("src/doc/man");
let man_dst = image.join("share/man/man1");
let month_year = t!(time::strftime("%B %Y", &time::now()));

// Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
let time = env::var("SOURCE_DATE_EPOCH")
.map(|timestamp| {
let epoch = timestamp.parse().map_err(|err| {
format!("could not parse SOURCE_DATE_EPOCH: {}", err)
}).unwrap();

time::at(Timespec::new(epoch, 0))
})
.unwrap_or_else(|_| time::now());

let month_year = t!(time::strftime("%B %Y", &time));
// don't use our `bootstrap::util::{copy, cp_r}`, because those try
// to hardlink, and we don't want to edit the source templates
for file_entry in builder.read_dir(&man_src) {
@@ -71,6 +71,10 @@ accomplishing various tasks.
</form>
</div>

## The Edition Guide

[The Edition Guide](edition-guide/index.html) describes the Rust editions.

## The Rustc Book

[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
@@ -433,6 +433,27 @@ impl<T: ?Sized> Rc<T> {
}
}

/// Consumes the `Rc`, returning the wrapped pointer as `NonNull<T>`.
///
/// # Examples
///
/// ```
/// #![feature(rc_into_raw_non_null)]
///
/// use std::rc::Rc;
///
/// let x = Rc::new(10);
/// let ptr = Rc::into_raw_non_null(x);
/// let deref = unsafe { *ptr.as_ref() };
/// assert_eq!(deref, 10);
/// ```
#[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
#[inline]
pub fn into_raw_non_null(this: Self) -> NonNull<T> {
// safe because Rc guarantees its pointer is non-null
unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) }
}

/// Creates a new [`Weak`][weak] pointer to this value.
///
/// [weak]: struct.Weak.html
@@ -413,6 +413,27 @@ impl<T: ?Sized> Arc<T> {
}
}

/// Consumes the `Arc`, returning the wrapped pointer as `NonNull<T>`.
///
/// # Examples
///
/// ```
/// #![feature(rc_into_raw_non_null)]
///
/// use std::sync::Arc;
///
/// let x = Arc::new(10);
/// let ptr = Arc::into_raw_non_null(x);
/// let deref = unsafe { *ptr.as_ref() };
/// assert_eq!(deref, 10);
/// ```
#[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
#[inline]
pub fn into_raw_non_null(this: Self) -> NonNull<T> {
// safe because Arc guarantees its pointer is non-null
unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) }
}

/// Creates a new [`Weak`][weak] pointer to this value.
///
/// [weak]: struct.Weak.html
@@ -3489,6 +3489,8 @@ impl str {
///
/// assert_eq!("Hello\tworld", s.trim());
/// ```
#[must_use = "this returns the trimmed string as a slice, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn trim(&self) -> &str {
self.trim_matches(|c: char| c.is_whitespace())
@@ -3524,6 +3526,8 @@ impl str {
/// let s = " עברית ";
/// assert!(Some('ע') == s.trim_start().chars().next());
/// ```
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
pub fn trim_start(&self) -> &str {
self.trim_start_matches(|c: char| c.is_whitespace())
@@ -3559,6 +3563,8 @@ impl str {
/// let s = " עברית ";
/// assert!(Some('ת') == s.trim_end().chars().rev().next());
/// ```
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
pub fn trim_end(&self) -> &str {
self.trim_end_matches(|c: char| c.is_whitespace())
@@ -3661,6 +3667,8 @@ impl str {
/// ```
/// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
/// ```
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
where P::Searcher: DoubleEndedSearcher<'a>
@@ -3706,6 +3714,8 @@ impl str {
/// let x: &[_] = &['1', '2'];
/// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
/// ```
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
let mut i = self.len();
@@ -3749,6 +3759,8 @@ impl str {
/// ```
/// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
/// ```
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
where P::Searcher: ReverseSearcher<'a>
@@ -3774,10 +3786,10 @@ impl str {
///
/// # Text directionality
///
/// A string is a sequence of bytes. 'Left' in this context means the first
/// position of that byte string; for a language like Arabic or Hebrew
/// which are 'right to left' rather than 'left to right', this will be
/// the _right_ side, not the left.
/// A string is a sequence of bytes. `start` in this context means the first
/// position of that byte string; for a left-to-right language like English or
/// Russian, this will be left side; and for right-to-left languages like
/// like Arabic or Hebrew, this will be the right side.
///
/// # Examples
///
@@ -3806,10 +3818,10 @@ impl str {
///
/// # Text directionality
///
/// A string is a sequence of bytes. 'Right' in this context means the last
/// position of that byte string; for a language like Arabic or Hebrew
/// which are 'right to left' rather than 'left to right', this will be
/// the _left_ side, not the right.
/// A string is a sequence of bytes. `end` in this context means the last
/// position of that byte string; for a left-to-right language like English or
/// Russian, this will be right side; and for right-to-left languages like
/// like Arabic or Hebrew, this will be the left side.
///
/// # Examples
///
@@ -14,7 +14,7 @@ pub struct RawConst<'tcx> {
}

/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
/// matches the LocalState optimizations for easy conversions between Value and ConstValue.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
/// Used only for types with layout::abi::Scalar ABI and ZSTs
@@ -147,6 +147,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[
("fxsr", None),
("lzcnt", None),
("mmx", Some("mmx_target_feature")),
("movbe", Some("movbe_target_feature")),
("pclmulqdq", None),
("popcnt", None),
("rdrand", None),
@@ -215,8 +215,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
if places_conflict::places_conflict(
self.tcx,
self.mir,
place,
&borrow_data.borrowed_place,
place,
places_conflict::PlaceConflictBias::NoOverlap,
) {
debug!(
@@ -76,8 +76,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
/// The locals are stored as `Option<Value>`s.
/// `None` represents a local that is currently dead, while a live local
/// can either directly contain `Scalar` or refer to some part of an `Allocation`.
pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
pub locals: IndexVec<mir::Local, LocalState<'tcx, Tag>>,

////////////////////////////////////////////////////////////////////////////////
// Current position within the function
@@ -106,7 +105,15 @@ pub enum StackPopCleanup {
None { cleanup: bool },
}

// State of a local variable
/// State of a local variable including a memoized layout
#[derive(Clone, PartialEq, Eq)]
pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
pub state: LocalValue<Tag, Id>,
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
pub layout: Cell<Option<TyLayout<'tcx>>>,
}

/// State of a local variable
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum LocalValue<Tag=(), Id=AllocId> {
Dead,
@@ -117,16 +124,16 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
Live(Operand<Tag, Id>),
}

impl<'tcx, Tag> LocalValue<Tag> {
impl<'tcx, Tag> LocalState<'tcx, Tag> {
pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
match self {
match self.state {
LocalValue::Dead => err!(DeadLocal),
LocalValue::Live(ref val) => Ok(val),
}
}

pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
match self {
match self.state {
LocalValue::Dead => err!(DeadLocal),
LocalValue::Live(ref mut val) => Ok(val),
}
@@ -310,17 +317,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
pub fn layout_of_local(
&self,
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
local: mir::Local
local: mir::Local,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, TyLayout<'tcx>> {
let cell = &frame.local_layouts[local];
if cell.get().is_none() {
let local_ty = frame.mir.local_decls[local].ty;
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
let layout = self.layout_of(local_ty)?;
cell.set(Some(layout));
match frame.locals[local].layout.get() {
None => {
let layout = ::interpret::operand::from_known_layout(layout, || {
let local_ty = frame.mir.local_decls[local].ty;
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
self.layout_of(local_ty)
})?;
frame.locals[local].layout.set(Some(layout));
Ok(layout)
}
Some(layout) => Ok(layout),
}

Ok(cell.get().unwrap())
}

pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
@@ -454,7 +465,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
// empty local array, we fill it in below, after we are inside the stack frame and
// all methods actually know about the frame
locals: IndexVec::new(),
local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
span,
instance,
stmt: 0,
@@ -466,12 +476,16 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
// We put some marker immediate into the locals that we later want to initialize.
// This can be anything except for LocalValue::Dead -- because *that* is the
// value we use for things that we know are initially dead.
let dummy =
LocalValue::Live(Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)));
let dummy = LocalState {
state: LocalValue::Live(Operand::Immediate(Immediate::Scalar(
ScalarMaybeUndef::Undef,
))),
layout: Cell::new(None),
};
let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
// Return place is handled specially by the `eval_place` functions, and the
// entry in `locals` should never be used. Make it dead, to be sure.
locals[mir::RETURN_PLACE] = LocalValue::Dead;
locals[mir::RETURN_PLACE].state = LocalValue::Dead;
// Now mark those locals as dead that we do not want to initialize
match self.tcx.describe_def(instance.def_id()) {
// statics and constants don't have `Storage*` statements, no need to look for them
@@ -484,7 +498,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
match stmt.kind {
StorageLive(local) |
StorageDead(local) => {
locals[local] = LocalValue::Dead;
locals[local].state = LocalValue::Dead;
}
_ => {}
}
@@ -494,11 +508,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}
// Finally, properly initialize all those that still have the dummy value
for (idx, local) in locals.iter_enumerated_mut() {
match *local {
match local.state {
LocalValue::Live(_) => {
// This needs to be peoperly initialized.
let layout = self.layout_of_local(self.frame(), idx)?;
*local = LocalValue::Live(self.uninit_operand(layout)?);
// This needs to be properly initialized.
let ty = self.monomorphize(mir.local_decls[idx].ty)?;
let layout = self.layout_of(ty)?;
local.state = LocalValue::Live(self.uninit_operand(layout)?);
local.layout = Cell::new(Some(layout));
}
LocalValue::Dead => {
// Nothing to do
@@ -543,7 +559,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}
// Deallocate all locals that are backed by an allocation.
for local in frame.locals {
self.deallocate_local(local)?;
self.deallocate_local(local.state)?;
}
// Validate the return value. Do this after deallocating so that we catch dangling
// references.
@@ -591,10 +607,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
trace!("{:?} is now live", local);

let layout = self.layout_of_local(self.frame(), local)?;
let layout = self.layout_of_local(self.frame(), local, None)?;
let init = LocalValue::Live(self.uninit_operand(layout)?);
// StorageLive *always* kills the value that's currently stored
Ok(mem::replace(&mut self.frame_mut().locals[local], init))
Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
}

/// Returns the old value of the local.
@@ -603,7 +619,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
trace!("{:?} is now dead", local);

mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
mem::replace(&mut self.frame_mut().locals[local].state, LocalValue::Dead)
}

pub(super) fn deallocate_local(
@@ -18,7 +18,7 @@ mod visitor;
pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here

pub use self::eval_context::{
EvalContext, Frame, StackPopCleanup, LocalValue,
EvalContext, Frame, StackPopCleanup, LocalState, LocalValue,
};

pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
Oops, something went wrong.

0 comments on commit f40aaa6

Please sign in to comment.
You can’t perform that action at this time.