Skip to content

Commit

Permalink
Auto merge of #33927 - Manishearth:rollup, r=Manishearth
Browse files Browse the repository at this point in the history
Rollup of 15 pull requests

- Successful merges: #33820, #33821, #33822, #33824, #33825, #33831, #33832, #33848, #33849, #33852, #33854, #33856, #33859, #33860, #33861
- Failed merges:
  • Loading branch information
bors committed May 28, 2016
2 parents 7d68b3d + fe9a915 commit f1776fe
Show file tree
Hide file tree
Showing 36 changed files with 787 additions and 612 deletions.
41 changes: 34 additions & 7 deletions src/liballoc_system/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,40 @@ mod imp {
if align <= MIN_ALIGN {
libc::malloc(size as libc::size_t) as *mut u8
} else {
let mut out = ptr::null_mut();
let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
if ret != 0 {
ptr::null_mut()
} else {
out as *mut u8
}
aligned_malloc(size, align)
}
}

#[cfg(target_os = "android")]
unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
// On android we currently target API level 9 which unfortunately
// doesn't have the `posix_memalign` API used below. Instead we use
// `memalign`, but this unfortunately has the property on some systems
// where the memory returned cannot be deallocated by `free`!
//
// Upon closer inspection, however, this appears to work just fine with
// Android, so for this platform we should be fine to call `memalign`
// (which is present in API level 9). Some helpful references could
// possibly be chromium using memalign [1], attempts at documenting that
// memalign + free is ok [2] [3], or the current source of chromium
// which still uses memalign on android [4].
//
// [1]: https://codereview.chromium.org/10796020/
// [2]: https://code.google.com/p/android/issues/detail?id=35391
// [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
// [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
// /memory/aligned_memory.cc
libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8
}

#[cfg(not(target_os = "android"))]
unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 {
let mut out = ptr::null_mut();
let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
if ret != 0 {
ptr::null_mut()
} else {
out as *mut u8
}
}

Expand Down
78 changes: 50 additions & 28 deletions src/libcore/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,17 @@ pub struct EscapeUnicode {
hex_digit_idx: usize,
}

// The enum values are ordered so that their representation is the
// same as the remaining length (besides the hexadecimal digits). This
// likely makes `len()` a single load from memory) and inline-worth.
#[derive(Clone, Debug)]
enum EscapeUnicodeState {
Backslash,
Type,
LeftBrace,
Value,
RightBrace,
Done,
RightBrace,
Value,
LeftBrace,
Type,
Backslash,
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -457,19 +460,17 @@ impl Iterator for EscapeUnicode {
}
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let n = match self.state {
EscapeUnicodeState::Backslash => 5,
EscapeUnicodeState::Type => 4,
EscapeUnicodeState::LeftBrace => 3,
EscapeUnicodeState::Value => 2,
EscapeUnicodeState::RightBrace => 1,
EscapeUnicodeState::Done => 0,
};
let n = n + self.hex_digit_idx;
let n = self.len();
(n, Some(n))
}

#[inline]
fn count(self) -> usize {
self.len()
}

fn last(self) -> Option<char> {
match self.state {
EscapeUnicodeState::Done => None,
Expand All @@ -483,6 +484,22 @@ impl Iterator for EscapeUnicode {
}
}

#[stable(feature = "exact_size_escape", since = "1.11.0")]
impl ExactSizeIterator for EscapeUnicode {
#[inline]
fn len(&self) -> usize {
// The match is a single memory access with no branching
self.hex_digit_idx + match self.state {
EscapeUnicodeState::Done => 0,
EscapeUnicodeState::RightBrace => 1,
EscapeUnicodeState::Value => 2,
EscapeUnicodeState::LeftBrace => 3,
EscapeUnicodeState::Type => 4,
EscapeUnicodeState::Backslash => 5,
}
}
}

/// An iterator that yields the literal escape code of a `char`.
///
/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
Expand All @@ -498,9 +515,9 @@ pub struct EscapeDefault {

#[derive(Clone, Debug)]
enum EscapeDefaultState {
Backslash(char),
Char(char),
Done,
Char(char),
Backslash(char),
Unicode(EscapeUnicode),
}

Expand All @@ -523,22 +540,15 @@ impl Iterator for EscapeDefault {
}
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.state {
EscapeDefaultState::Char(_) => (1, Some(1)),
EscapeDefaultState::Backslash(_) => (2, Some(2)),
EscapeDefaultState::Unicode(ref iter) => iter.size_hint(),
EscapeDefaultState::Done => (0, Some(0)),
}
let n = self.len();
(n, Some(n))
}

#[inline]
fn count(self) -> usize {
match self.state {
EscapeDefaultState::Char(_) => 1,
EscapeDefaultState::Unicode(iter) => iter.count(),
EscapeDefaultState::Done => 0,
EscapeDefaultState::Backslash(_) => 2,
}
self.len()
}

fn nth(&mut self, n: usize) -> Option<char> {
Expand Down Expand Up @@ -578,6 +588,18 @@ impl Iterator for EscapeDefault {
}
}

#[stable(feature = "exact_size_escape", since = "1.11.0")]
impl ExactSizeIterator for EscapeDefault {
fn len(&self) -> usize {
match self.state {
EscapeDefaultState::Done => 0,
EscapeDefaultState::Char(_) => 1,
EscapeDefaultState::Backslash(_) => 2,
EscapeDefaultState::Unicode(ref iter) => iter.len(),
}
}
}

/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
/// value.
///
Expand Down
6 changes: 6 additions & 0 deletions src/libcoretest/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ fn eu_iterator_specializations() {
// Check last
assert_eq!(iter.clone().last(), Some('}'));

// Check len
assert_eq!(iter.len(), len - offset);

// Check size_hint (= len in ExactSizeIterator)
assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len())));

// Check counting
assert_eq!(iter.clone().count(), len - offset);

Expand Down
15 changes: 4 additions & 11 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_path(path, item.id);
}
ViewPathList(ref prefix, ref list) => {
if !list.is_empty() {
for item in list {
visitor.visit_path_list_item(prefix, item)
}
} else {
visitor.visit_path(prefix, item.id);
visitor.visit_path(prefix, item.id);
for item in list {
visitor.visit_path_list_item(prefix, item)
}
}
}
Expand Down Expand Up @@ -419,12 +416,8 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
}

pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
prefix: &'v Path,
_prefix: &'v Path,
item: &'v PathListItem) {
for segment in &prefix.segments {
visitor.visit_path_segment(prefix.span, segment);
}

walk_opt_name(visitor, item.span, item.node.name());
walk_opt_name(visitor, item.span, item.node.rename());
}
Expand Down
33 changes: 28 additions & 5 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
// If the number of errors increases, that's also a sign (line
// `tained_by_errors`) to avoid reporting certain kinds of errors.
err_count_on_creation: usize,

// This flag is used for debugging, and is set to true if there are
// any obligations set during the current snapshot. In that case, the
// snapshot can't be rolled back.
pub obligations_in_snapshot: Cell<bool>,
}

/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
Expand Down Expand Up @@ -476,7 +481,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
normalize: false,
projection_mode: ProjectionMode::AnyFinal,
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: self.sess.err_count()
err_count_on_creation: self.sess.err_count(),
obligations_in_snapshot: Cell::new(false),
}
}
}
Expand Down Expand Up @@ -515,7 +521,8 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
normalize: normalize,
projection_mode: projection_mode,
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: tcx.sess.err_count()
err_count_on_creation: tcx.sess.err_count(),
obligations_in_snapshot: Cell::new(false),
}))
}
}
Expand All @@ -542,6 +549,7 @@ pub struct CombinedSnapshot {
int_snapshot: unify::Snapshot<ty::IntVid>,
float_snapshot: unify::Snapshot<ty::FloatVid>,
region_vars_snapshot: RegionSnapshot,
obligations_in_snapshot: bool,
}

/// Helper trait for shortening the lifetimes inside a
Expand Down Expand Up @@ -809,11 +817,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

fn start_snapshot(&self) -> CombinedSnapshot {
let obligations_in_snapshot = self.obligations_in_snapshot.get();
self.obligations_in_snapshot.set(false);

CombinedSnapshot {
type_snapshot: self.type_variables.borrow_mut().snapshot(),
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
region_vars_snapshot: self.region_vars.start_snapshot(),
obligations_in_snapshot: obligations_in_snapshot,
}
}

Expand All @@ -822,7 +834,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let CombinedSnapshot { type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = snapshot;
region_vars_snapshot,
obligations_in_snapshot } = snapshot;

assert!(!self.obligations_in_snapshot.get());
self.obligations_in_snapshot.set(obligations_in_snapshot);

self.type_variables
.borrow_mut()
Expand All @@ -842,7 +858,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let CombinedSnapshot { type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = snapshot;
region_vars_snapshot,
obligations_in_snapshot } = snapshot;

self.obligations_in_snapshot.set(obligations_in_snapshot);

self.type_variables
.borrow_mut()
Expand Down Expand Up @@ -904,12 +923,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let CombinedSnapshot { type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = self.start_snapshot();
region_vars_snapshot,
obligations_in_snapshot } = self.start_snapshot();

let r = self.commit_if_ok(|_| f());

debug!("commit_regions_if_ok: rolling back everything but regions");

assert!(!self.obligations_in_snapshot.get());
self.obligations_in_snapshot.set(obligations_in_snapshot);

// Roll back any non-region bindings - they should be resolved
// inside `f`, with, e.g. `resolve_type_vars_if_possible`.
self.type_variables
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
// debug output much nicer to read and so on.
let obligation = infcx.resolve_type_vars_if_possible(&obligation);

infcx.obligations_in_snapshot.set(true);

if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate)
{
return
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub use self::coherence::overlapping_impls;
pub use self::coherence::OrphanCheckErr;
pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
pub use self::project::{MismatchedProjectionTypes, ProjectionMode};
pub use self::project::{normalize, Normalized};
pub use self::project::{normalize, normalize_projection_type, Normalized};
pub use self::object_safety::ObjectSafetyViolation;
pub use self::object_safety::MethodViolationCode;
pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
Expand Down
Loading

0 comments on commit f1776fe

Please sign in to comment.