Auto merge of #41098 - arielb1:rollup, r=arielb1

Rollup of 12 pull requests

- Successful merges: #40479, #40561, #40709, #40815, #40909, #40927, #40943, #41015, #41028, #41052, #41054, #41065
- Failed merges:
This commit is contained in:
bors 2017-04-06 01:00:15 +00:00
commit 6cd15a0e8f
27 changed files with 1280 additions and 1092 deletions

View File

@ -49,12 +49,17 @@ pub fn install(build: &Build, stage: u32, host: &str) {
install_sh(&build, "docs", "rust-docs", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
for target in build.config.target.iter() {
install_sh(&build, "std", "rust-std", stage, target, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
if build.config.rust_save_analysis {
install_sh(&build, "analysis", "rust-analysis", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
}
install_sh(&build, "std", "rust-std", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
install_sh(&build, "rustc", "rustc", stage, host, &prefix,
&docdir, &libdir, &mandir, &empty_dir);
t!(fs::remove_dir_all(&empty_dir));

View File

@ -123,6 +123,7 @@
- [no_debug](no-debug.md)
- [non_ascii_idents](non-ascii-idents.md)
- [nonzero](nonzero.md)
- [offset_to](offset-to.md)
- [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
- [on_unimplemented](on-unimplemented.md)
- [once_poison](once-poison.md)
@ -171,6 +172,7 @@
- [slice_concat_ext](slice-concat-ext.md)
- [slice_get_slice](slice-get-slice.md)
- [slice_patterns](slice-patterns.md)
- [slice_rsplit](slice-rsplit.md)
- [sort_internals](sort-internals.md)
- [sort_unstable](sort-unstable.md)
- [specialization](specialization.md)

View File

@ -0,0 +1,7 @@
# `offset_to`
The tracking issue for this feature is: [#41079]
[#41079]: https://github.com/rust-lang/rust/issues/41079
------------------------

View File

@ -0,0 +1,10 @@
# `slice_rsplit`
The tracking issue for this feature is: [#41020]
[#41020]: https://github.com/rust-lang/rust/issues/41020
------------------------
The `slice_rsplit` feature enables two methods on slices:
`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`.

View File

@ -76,6 +76,66 @@ def get_codepoints(f):
for c in range(prev_codepoint + 1, NUM_CODEPOINTS):
yield Codepoint(c, None)
def compress_singletons(singletons):
uppers = [] # (upper, # items in lowers)
lowers = []
for i in singletons:
upper = i >> 8
lower = i & 0xff
if len(uppers) == 0 or uppers[-1][0] != upper:
uppers.append((upper, 1))
else:
upper, count = uppers[-1]
uppers[-1] = upper, count + 1
lowers.append(lower)
return uppers, lowers
def compress_normal(normal):
# lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f
# lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff
compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)]
prev_start = 0
for start, count in normal:
truelen = start - prev_start
falselen = count
prev_start = start + count
assert truelen < 0x8000 and falselen < 0x8000
entry = []
if truelen > 0x7f:
entry.append(0x80 | (truelen >> 8))
entry.append(truelen & 0xff)
else:
entry.append(truelen & 0x7f)
if falselen > 0x7f:
entry.append(0x80 | (falselen >> 8))
entry.append(falselen & 0xff)
else:
entry.append(falselen & 0x7f)
compressed.append(entry)
return compressed
def print_singletons(uppers, lowers, uppersname, lowersname):
print("const {}: &'static [(u8, u8)] = &[".format(uppersname))
for u, c in uppers:
print(" ({:#04x}, {}),".format(u, c))
print("];")
print("const {}: &'static [u8] = &[".format(lowersname))
for i in range(0, len(lowers), 8):
print(" {}".format(" ".join("{:#04x},".format(l) for l in lowers[i:i+8])))
print("];")
def print_normal(normal, normalname):
print("const {}: &'static [u8] = &[".format(normalname))
for v in normal:
print(" {}".format(" ".join("{:#04x},".format(i) for i in v)))
print("];")
def main():
file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
@ -111,6 +171,11 @@ def main():
else:
normal0.append((a, b - a))
singletons0u, singletons0l = compress_singletons(singletons0)
singletons1u, singletons1l = compress_singletons(singletons1)
normal0 = compress_normal(normal0)
normal1 = compress_normal(normal1)
print("""\
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
@ -125,38 +190,49 @@ def main():
// NOTE: The following code was generated by "src/etc/char_private.py",
// do not edit directly!
use slice::SliceExt;
fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
for &s in singletons {
if x == s {
return false;
} else if x < s {
break;
}
}
for w in normal.chunks(2) {
let start = w[0];
let len = w[1];
let difference = (x as i32) - (start as i32);
if 0 <= difference {
if difference < len as i32 {
return false;
fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
normal: &[u8]) -> bool {
let xupper = (x >> 8) as u8;
let mut lowerstart = 0;
for &(upper, lowercount) in singletonuppers {
let lowerend = lowerstart + lowercount as usize;
if xupper == upper {
for &lower in &singletonlowers[lowerstart..lowerend] {
if lower == x as u8 {
return false;
}
}
} else {
} else if xupper < upper {
break;
}
lowerstart = lowerend;
}
true
let mut x = x as i32;
let mut normal = normal.iter().cloned();
let mut current = true;
while let Some(v) = normal.next() {
let len = if v & 0x80 != 0 {
((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32
} else {
v as i32
};
x -= len;
if x < 0 {
break;
}
current = !current;
}
current
}
pub fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
check(lower, SINGLETONS0, NORMAL0)
check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
} else if x < 0x20000 {
check(lower, SINGLETONS1, NORMAL1)
check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
} else {\
""")
for a, b in extra:
@ -169,22 +245,10 @@ pub fn is_printable(x: char) -> bool {
}\
""")
print()
print("const SINGLETONS0: &'static [u16] = &[")
for s in singletons0:
print(" 0x{:x},".format(s))
print("];")
print("const SINGLETONS1: &'static [u16] = &[")
for s in singletons1:
print(" 0x{:x},".format(s))
print("];")
print("const NORMAL0: &'static [u16] = &[")
for a, b in normal0:
print(" 0x{:x}, 0x{:x},".format(a, b))
print("];")
print("const NORMAL1: &'static [u16] = &[")
for a, b in normal1:
print(" 0x{:x}, 0x{:x},".format(a, b))
print("];")
print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L')
print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L')
print_normal(normal0, 'NORMAL0')
print_normal(normal1, 'NORMAL1')
if __name__ == '__main__':
main()

View File

@ -52,6 +52,7 @@
#![feature(shared)]
#![feature(slice_get_slice)]
#![feature(slice_patterns)]
#![feature(slice_rsplit)]
#![cfg_attr(not(test), feature(sort_unstable))]
#![feature(specialization)]
#![feature(staged_api)]
@ -62,6 +63,7 @@
#![feature(untagged_unions)]
#![cfg_attr(not(test), feature(str_checked_slicing))]
#![cfg_attr(test, feature(rand, test))]
#![feature(offset_to)]
#![no_std]

View File

@ -115,6 +115,8 @@
pub use core::slice::{SplitMut, ChunksMut, Split};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
#[unstable(feature = "slice_rsplit", issue = "41020")]
pub use core::slice::{RSplit, RSplitMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
#[unstable(feature = "slice_get_slice", issue = "35729")]
@ -779,6 +781,72 @@ pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
core_slice::SliceExt::split_mut(self, pred)
}
/// Returns an iterator over subslices separated by elements that match
/// `pred`, starting at the end of the slice and working backwards.
/// The matched element is not contained in the subslices.
///
/// # Examples
///
/// ```
/// #![feature(slice_rsplit)]
///
/// let slice = [11, 22, 33, 0, 44, 55];
/// let mut iter = slice.rsplit(|num| *num == 0);
///
/// assert_eq!(iter.next().unwrap(), &[44, 55]);
/// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
/// assert_eq!(iter.next(), None);
/// ```
///
/// As with `split()`, if the first or last element is matched, an empty
/// slice will be the first (or last) item returned by the iterator.
///
/// ```
/// #![feature(slice_rsplit)]
///
/// let v = &[0, 1, 1, 2, 3, 5, 8];
/// let mut it = v.rsplit(|n| *n % 2 == 0);
/// assert_eq!(it.next().unwrap(), &[]);
/// assert_eq!(it.next().unwrap(), &[3, 5]);
/// assert_eq!(it.next().unwrap(), &[1, 1]);
/// assert_eq!(it.next().unwrap(), &[]);
/// assert_eq!(it.next(), None);
/// ```
#[unstable(feature = "slice_rsplit", issue = "41020")]
#[inline]
pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
where F: FnMut(&T) -> bool
{
core_slice::SliceExt::rsplit(self, pred)
}
/// Returns an iterator over mutable subslices separated by elements that
/// match `pred`, starting at the end of the slice and working
/// backwards. The matched element is not contained in the subslices.
///
/// # Examples
///
/// ```
/// #![feature(slice_rsplit)]
///
/// let mut v = [100, 400, 300, 200, 600, 500];
///
/// let mut count = 0;
/// for group in v.rsplit_mut(|num| *num % 3 == 0) {
/// count += 1;
/// group[0] = count;
/// }
/// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
/// ```
///
#[unstable(feature = "slice_rsplit", issue = "41020")]
#[inline]
pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
where F: FnMut(&T) -> bool
{
core_slice::SliceExt::rsplit_mut(self, pred)
}
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to returning at most `n` items. The matched element is
/// not contained in the subslices.

View File

@ -973,6 +973,29 @@ pub fn push(&mut self, value: T) {
}
}
/// Returns a place for insertion at the back of the `Vec`.
///
/// Using this method with placement syntax is equivalent to [`push`](#method.push),
/// but may be more efficient.
///
/// # Examples
///
/// ```
/// #![feature(collection_placement)]
/// #![feature(placement_in_syntax)]
///
/// let mut vec = vec![1, 2];
/// vec.place_back() <- 3;
/// vec.place_back() <- 4;
/// assert_eq!(&vec, &[1, 2, 3, 4]);
/// ```
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
pub fn place_back(&mut self) -> PlaceBack<T> {
PlaceBack { vec: self }
}
/// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty.
///
@ -1267,29 +1290,6 @@ fn extend_with_element(&mut self, n: usize, value: T) {
pub fn extend_from_slice(&mut self, other: &[T]) {
self.spec_extend(other.iter())
}
/// Returns a place for insertion at the back of the `Vec`.
///
/// Using this method with placement syntax is equivalent to [`push`](#method.push),
/// but may be more efficient.
///
/// # Examples
///
/// ```
/// #![feature(collection_placement)]
/// #![feature(placement_in_syntax)]
///
/// let mut vec = vec![1, 2];
/// vec.place_back() <- 3;
/// vec.place_back() <- 4;
/// assert_eq!(&vec, &[1, 2, 3, 4]);
/// ```
#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
pub fn place_back(&mut self) -> PlaceBack<T> {
PlaceBack { vec: self }
}
}
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
@ -2074,14 +2074,10 @@ fn next(&mut self) -> Option<T> {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let diff = (self.end as usize) - (self.ptr as usize);
let size = mem::size_of::<T>();
let exact = diff /
(if size == 0 {
1
} else {
size
});
let exact = match self.ptr.offset_to(self.end) {
Some(x) => x as usize,
None => (self.end as usize).wrapping_sub(self.ptr as usize),
};
(exact, Some(exact))
}

File diff suppressed because it is too large Load Diff

View File

@ -358,12 +358,24 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
fn next(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next_back() }
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where P: FnMut(&Self::Item) -> bool
{
self.iter.rfind(predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
#[inline]
fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where P: FnMut(&Self::Item) -> bool
{
self.iter.find(predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -467,7 +467,7 @@ fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
Self: Sized,
P: FnMut(&Self::Item) -> bool
{
for x in self.by_ref().rev() {
while let Some(x) = self.next_back() {
if predicate(&x) { return Some(x) }
}
None

View File

@ -500,6 +500,44 @@ pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
intrinsics::arith_offset(self, count)
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// If the address different between the two pointers ia not a multiple of
/// `mem::size_of::<T>()` then the result of the division is rounded towards
/// zero.
///
/// This function returns `None` if `T` is a zero-sized typed.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(offset_to)]
///
/// fn main() {
/// let a = [0; 5];
/// let ptr1: *const i32 = &a[1];
/// let ptr2: *const i32 = &a[3];
/// assert_eq!(ptr1.offset_to(ptr2), Some(2));
/// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
/// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
/// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
/// }
/// ```
#[unstable(feature = "offset_to", issue = "41079")]
#[inline]
pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
let size = mem::size_of::<T>();
if size == 0 {
None
} else {
let diff = (other as isize).wrapping_sub(self as isize);
Some(diff / size as isize)
}
}
}
#[lang = "mut_ptr"]
@ -653,6 +691,44 @@ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
Some(&mut *self)
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// If the address different between the two pointers ia not a multiple of
/// `mem::size_of::<T>()` then the result of the division is rounded towards
/// zero.
///
/// This function returns `None` if `T` is a zero-sized typed.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(offset_to)]
///
/// fn main() {
/// let mut a = [0; 5];
/// let ptr1: *mut i32 = &mut a[1];
/// let ptr2: *mut i32 = &mut a[3];
/// assert_eq!(ptr1.offset_to(ptr2), Some(2));
/// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
/// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
/// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
/// }
/// ```
#[unstable(feature = "offset_to", issue = "41079")]
#[inline]
pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
let size = mem::size_of::<T>();
if size == 0 {
None
} else {
let diff = (other as isize).wrapping_sub(self as isize);
Some(diff / size as isize)
}
}
}
// Equality for pointers

View File

@ -81,6 +81,10 @@ pub trait SliceExt {
fn split<P>(&self, pred: P) -> Split<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
#[unstable(feature = "slice_rsplit", issue = "41020")]
fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
#[stable(feature = "core", since = "1.6.0")]
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
@ -159,6 +163,10 @@ fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
#[unstable(feature = "slice_rsplit", issue = "41020")]
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
#[stable(feature = "core", since = "1.6.0")]
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
@ -293,6 +301,13 @@ fn split<P>(&self, pred: P) -> Split<T, P>
}
}
#[inline]
fn rsplit<P>(&self, pred: P) -> RSplit<T, P>
where P: FnMut(&T) -> bool
{
RSplit { inner: self.split(pred) }
}
#[inline]
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
where P: FnMut(&T) -> bool
@ -300,8 +315,7 @@ fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
SplitN {
inner: GenericSplitN {
iter: self.split(pred),
count: n,
invert: false
count: n
}
}
}
@ -312,9 +326,8 @@ fn rsplitn<P>(&self, n: usize, pred: P) -> RSplitN<T, P>
{
RSplitN {
inner: GenericSplitN {
iter: self.split(pred),
count: n,
invert: true
iter: self.rsplit(pred),
count: n
}
}
}
@ -475,6 +488,13 @@ fn split_mut<P>(&mut self, pred: P) -> SplitMut<T, P>
SplitMut { v: self, pred: pred, finished: false }
}
#[inline]
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
where P: FnMut(&T) -> bool
{
RSplitMut { inner: self.split_mut(pred) }
}
#[inline]
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
where P: FnMut(&T) -> bool
@ -482,8 +502,7 @@ fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
SplitNMut {
inner: GenericSplitN {
iter: self.split_mut(pred),
count: n,
invert: false
count: n
}
}
}
@ -494,9 +513,8 @@ fn rsplitn_mut<P>(&mut self, n: usize, pred: P) -> RSplitNMut<T, P> where
{
RSplitNMut {
inner: GenericSplitN {
iter: self.split_mut(pred),
count: n,
invert: true
iter: self.rsplit_mut(pred),
count: n
}
}
}
@ -1498,9 +1516,10 @@ unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
// Return the arithmetic difference if `T` is zero size.
#[inline(always)]
fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
let diff = (end as usize).wrapping_sub(start as usize);
let size = mem::size_of::<T>();
diff / (if size == 0 { 1 } else { size })
match start.offset_to(end) {
Some(x) => x as usize,
None => (end as usize).wrapping_sub(start as usize),
}
}
// Extension methods for raw pointers, used by the iterators
@ -1735,6 +1754,123 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
/// An iterator over subslices separated by elements that match a predicate
/// function, starting from the end of the slice.
///
/// This struct is created by the [`rsplit`] method on [slices].
///
/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature = "slice_rsplit", issue = "41020")]
#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
inner: Split<'a, T, P>
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RSplit")
.field("v", &self.inner.v)
.field("finished", &self.inner.finished)
.finish()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
type Item = &'a [T];
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
self.inner.next_back()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
self.inner.next()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
#[inline]
fn finish(&mut self) -> Option<&'a [T]> {
self.inner.finish()
}
}
//#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
/// An iterator over the subslices of the vector which are separated
/// by elements that match `pred`, starting from the end of the slice.
///
/// This struct is created by the [`rsplit_mut`] method on [slices].
///
/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature = "slice_rsplit", issue = "41020")]
pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
inner: SplitMut<'a, T, P>
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RSplitMut")
.field("v", &self.inner.v)
.field("finished", &self.inner.finished)
.finish()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
#[inline]
fn finish(&mut self) -> Option<&'a mut [T]> {
self.inner.finish()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
type Item = &'a mut [T];
#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
self.inner.next_back()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
P: FnMut(&T) -> bool,
{
#[inline]
fn next_back(&mut self) -> Option<&'a mut [T]> {
self.inner.next()
}
}
//#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
/// An private iterator over subslices separated by elements that
/// match a predicate function, splitting at most a fixed number of
/// times.
@ -1742,7 +1878,6 @@ impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
struct GenericSplitN<I> {
iter: I,
count: usize,
invert: bool
}
impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
@ -1753,10 +1888,7 @@ fn next(&mut self) -> Option<T> {
match self.count {
0 => None,
1 => { self.count -= 1; self.iter.finish() }
_ => {
self.count -= 1;
if self.invert {self.iter.next_back()} else {self.iter.next()}
}
_ => { self.count -= 1; self.iter.next() }
}
}
@ -1798,7 +1930,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<Split<'a, T, P>>
inner: GenericSplitN<RSplit<'a, T, P>>
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
@ -1841,7 +1973,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// [slices]: ../../std/primitive.slice.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<SplitMut<'a, T, P>>
inner: GenericSplitN<RSplitMut<'a, T, P>>
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]

View File

@ -321,7 +321,7 @@ pub fn store(&self, val: bool, order: Ordering) {
}
}
/// Stores a value into the bool, returning the old value.
/// Stores a value into the bool, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
@ -732,7 +732,7 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
}
}
/// Stores a value into the pointer, returning the old value.
/// Stores a value into the pointer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering
/// of this operation.
@ -1047,7 +1047,7 @@ pub fn store(&self, val: $int_type, order: Ordering) {
unsafe { atomic_store(self.v.get(), val, order); }
}
/// Stores a value into the atomic integer, returning the old value.
/// Stores a value into the atomic integer, returning the previous value.
///
/// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
/// operation.
@ -1201,7 +1201,9 @@ pub fn compare_exchange_weak(&self,
}
}
/// Add to the current value, returning the previous value.
/// Adds to the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// # Examples
///
@ -1218,7 +1220,9 @@ pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
unsafe { atomic_add(self.v.get(), val, order) }
}
/// Subtract from the current value, returning the previous value.
/// Subtracts from the current value, returning the previous value.
///
/// This operation wraps around on overflow.
///
/// # Examples
///
@ -1235,7 +1239,12 @@ pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
unsafe { atomic_sub(self.v.get(), val, order) }
}
/// Bitwise and with the current value, returning the previous value.
/// Bitwise "and" with the current value.
///
/// Performs a bitwise "and" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// # Examples
///
@ -1251,7 +1260,12 @@ pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
unsafe { atomic_and(self.v.get(), val, order) }
}
/// Bitwise or with the current value, returning the previous value.
/// Bitwise "or" with the current value.
///
/// Performs a bitwise "or" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// # Examples
///
@ -1267,7 +1281,12 @@ pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
unsafe { atomic_or(self.v.get(), val, order) }
}
/// Bitwise xor with the current value, returning the previous value.
/// Bitwise "xor" with the current value.
///
/// Performs a bitwise "xor" operation on the current value and the argument `val`, and
/// sets the new value to the result.
///
/// Returns the previous value.
///
/// # Examples
///
@ -1415,7 +1434,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
}
/// Returns the old value (like __sync_fetch_and_add).
/// Returns the previous value (like __sync_fetch_and_add).
#[inline]
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
@ -1428,7 +1447,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
}
/// Returns the old value (like __sync_fetch_and_sub).
/// Returns the previous value (like __sync_fetch_and_sub).
#[inline]
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {

View File

@ -25,6 +25,9 @@ pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[blk]
}
// llvm.org/PR32488 makes this function use an excess of stack space. Mark
// it as #[inline(never)] to keep rustc's stack use in check.
#[inline(never)]
pub fn start_new_block(&mut self) -> BasicBlock {
self.basic_blocks.push(BasicBlockData::new(None))
}

View File

@ -11,7 +11,6 @@
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::lint;
use rustc::traits::{self, Reveal};
use rustc::ty::{self, TyCtxt};
@ -53,12 +52,16 @@ enum Namespace {
for &item2 in &impl_items2[..] {
if (name, namespace) == name_and_namespace(item2) {
let msg = format!("duplicate definitions with name `{}`", name);
let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
node_id,
self.tcx.span_of_impl(item1).unwrap(),
msg);
struct_span_err!(self.tcx.sess,
self.tcx.span_of_impl(item1).unwrap(),
E0592,
"duplicate definitions with name `{}`",
name)
.span_label(self.tcx.span_of_impl(item1).unwrap(),
&format!("duplicate definitions for `{}`", name))
.span_label(self.tcx.span_of_impl(item2).unwrap(),
&format!("other definition for `{}`", name))
.emit();
}
}
}

View File

@ -472,7 +472,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>)
}
// Now we've done all our shifting. Return the value we grabbed earlier.
(retkey, retval, gap.into_bucket().into_table())
(retkey, retval, gap.into_table())
}
/// Perform robin hood bucket stealing at the given `bucket`. You must
@ -485,14 +485,14 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
mut key: K,
mut val: V)
-> FullBucketMut<'a, K, V> {
let start_index = bucket.index();
let size = bucket.table().size();
// Save the *starting point*.
let mut bucket = bucket.stash();
let raw_capacity = bucket.table().capacity();
// There can be at most `size - dib` buckets to displace, because
// in the worst case, there are `size` elements and we already are
// `displacement` buckets away from the initial one.
let idx_end = start_index + size - bucket.displacement();
let idx_end = (bucket.index() + size - bucket.displacement()) % raw_capacity;
// Save the *starting point*.
let mut bucket = bucket.stash();
loop {
let (old_hash, old_key, old_val) = bucket.replace(hash, key, val);
@ -568,11 +568,8 @@ fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> InternalEntry<K, V, &'a mut
// The caller should ensure that invariants by Robin Hood Hashing hold
// and that there's space in the underlying table.
fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
let raw_cap = self.raw_capacity();
let mut buckets = Bucket::new(&mut self.table, hash);
// note that buckets.index() keeps increasing
// even if the pointer wraps back to the first bucket.
let limit_bucket = buckets.index() + raw_cap;
let start_index = buckets.index();
loop {
// We don't need to compare hashes for value swap.
@ -585,7 +582,7 @@ fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
Full(b) => b.into_bucket(),
};
buckets.next();
debug_assert!(buckets.index() < limit_bucket);
debug_assert!(buckets.index() != start_index);
}
}
}
@ -1244,24 +1241,25 @@ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&K, &mut V) -> bool
{
if self.table.capacity() == 0 || self.table.size() == 0 {
if self.table.size() == 0 {
return;
}
let mut elems_left = self.table.size();
let mut bucket = Bucket::head_bucket(&mut self.table);
bucket.prev();
let tail = bucket.index();
loop {
let start_index = bucket.index();
while elems_left != 0 {
bucket = match bucket.peek() {
Full(mut full) => {
elems_left -= 1;
let should_remove = {
let (k, v) = full.read_mut();
!f(k, v)
};
if should_remove {
let prev_idx = full.index();
let prev_raw = full.raw();
let (_, _, t) = pop_internal(full);
Bucket::new_from(prev_raw, prev_idx, t)
Bucket::new_from(prev_raw, t)
} else {
full.into_bucket()
}
@ -1271,9 +1269,7 @@ pub fn retain<F>(&mut self, mut f: F)
}
};
bucket.prev(); // reverse iteration
if bucket.index() == tail {
break;
}
debug_assert!(elems_left == 0 || bucket.index() != start_index);
}
}
}

View File

@ -113,7 +113,7 @@ fn ptr(&self) -> *mut HashUint {
/// when the RawTable is created and is accessible with the `tag` and `set_tag`
/// functions.
pub struct RawTable<K, V> {
capacity: usize,
capacity_mask: usize,
size: usize,
hashes: TaggedHashUintPtr,
@ -125,10 +125,13 @@ pub struct RawTable<K, V> {
unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
unsafe impl<K: Sync, V: Sync> Sync for RawTable<K, V> {}
// An unsafe view of a RawTable bucket
// Valid indexes are within [0..table_capacity)
pub struct RawBucket<K, V> {
hash: *mut HashUint,
hash_start: *mut HashUint,
// We use *const to ensure covariance with respect to K and V
pair: *const (K, V),
pair_start: *const (K, V),
idx: usize,
_marker: marker::PhantomData<(K, V)>,
}
@ -141,7 +144,6 @@ fn clone(&self) -> RawBucket<K, V> {
pub struct Bucket<K, V, M> {
raw: RawBucket<K, V>,
idx: usize,
table: M,
}
@ -154,13 +156,11 @@ fn clone(&self) -> Bucket<K, V, M> {
pub struct EmptyBucket<K, V, M> {
raw: RawBucket<K, V>,
idx: usize,
table: M,
}
pub struct FullBucket<K, V, M> {
raw: RawBucket<K, V>,
idx: usize,
table: M,
}
@ -232,13 +232,17 @@ fn can_alias_safehash_as_hash() {
assert_eq!(size_of::<SafeHash>(), size_of::<HashUint>())
}
// RawBucket methods are unsafe as it's possible to
// make a RawBucket point to invalid memory using safe code.
impl<K, V> RawBucket<K, V> {
unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
RawBucket {
hash: self.hash.offset(count),
pair: self.pair.offset(count),
_marker: marker::PhantomData,
}
unsafe fn hash(&self) -> *mut HashUint {
self.hash_start.offset(self.idx as isize)
}
unsafe fn pair(&self) -> *mut (K, V) {
self.pair_start.offset(self.idx as isize) as *mut (K, V)
}
unsafe fn hash_pair(&self) -> (*mut HashUint, *mut (K, V)) {
(self.hash(), self.pair())
}
}
@ -258,7 +262,7 @@ pub fn into_table(self) -> M {
}
/// Get the raw index.
pub fn index(&self) -> usize {
self.idx
self.raw.idx
}
/// Get the raw bucket.
pub fn raw(&self) -> RawBucket<K, V> {
@ -280,7 +284,7 @@ pub fn table_mut(&mut self) -> &mut M {
impl<K, V, M> Bucket<K, V, M> {
/// Get the raw index.
pub fn index(&self) -> usize {
self.idx
self.raw.idx
}
/// get the table.
pub fn into_table(self) -> M {
@ -331,12 +335,11 @@ pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
Bucket::at_index(table, hash.inspect() as usize)
}
pub fn new_from(r: RawBucket<K, V>, i: usize, t: M)
pub fn new_from(r: RawBucket<K, V>, t: M)
-> Bucket<K, V, M>
{
Bucket {
raw: r,
idx: i,
table: t,
}
}
@ -346,18 +349,16 @@ pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
// This is an uncommon case though, so avoid it in release builds.
debug_assert!(table.capacity() > 0,
"Table should have capacity at this point");
let ib_index = ib_index & (table.capacity() - 1);
let ib_index = ib_index & table.capacity_mask;
Bucket {
raw: unsafe { table.first_bucket_raw().offset(ib_index as isize) },
idx: ib_index,
raw: table.raw_bucket_at(ib_index),
table: table,
}
}
pub fn first(table: M) -> Bucket<K, V, M> {
Bucket {
raw: table.first_bucket_raw(),
idx: 0,
raw: table.raw_bucket_at(0),
table: table,
}
}
@ -401,48 +402,30 @@ pub fn head_bucket(table: M) -> Bucket<K, V, M> {
/// the appropriate types to call most of the other functions in
/// this module.
pub fn peek(self) -> BucketState<K, V, M> {
match unsafe { *self.raw.hash } {
match unsafe { *self.raw.hash() } {
EMPTY_BUCKET => {
Empty(EmptyBucket {
raw: self.raw,
idx: self.idx,
table: self.table,
})
}
_ => {
Full(FullBucket {
raw: self.raw,
idx: self.idx,
table: self.table,
})
}
}
}
/// Modifies the bucket pointer in place to make it point to the next slot.
/// Modifies the bucket in place to make it point to the next slot.
pub fn next(&mut self) {
self.idx += 1;
let range = self.table.capacity();
// This code is branchless thanks to a conditional move.
let dist = if self.idx & (range - 1) == 0 {
1 - range as isize
} else {
1
};
unsafe {
self.raw = self.raw.offset(dist);
}
self.raw.idx = self.raw.idx.wrapping_add(1) & self.table.capacity_mask;
}
/// Modifies the bucket pointer in place to make it point to the previous slot.
/// Modifies the bucket in place to make it point to the previous slot.
pub fn prev(&mut self) {
let range = self.table.capacity();
let new_idx = self.idx.wrapping_sub(1) & (range - 1);
let dist = (new_idx as isize).wrapping_sub(self.idx as isize);
self.idx = new_idx;
unsafe {
self.raw = self.raw.offset(dist);
}
self.raw.idx = self.raw.idx.wrapping_sub(1) & self.table.capacity_mask;
}
}
@ -458,7 +441,6 @@ pub fn next(self) -> Bucket<K, V, M> {
pub fn into_bucket(self) -> Bucket<K, V, M> {
Bucket {
raw: self.raw,
idx: self.idx,
table: self.table,
}
}
@ -466,7 +448,6 @@ pub fn into_bucket(self) -> Bucket<K, V, M> {
pub fn gap_peek(self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
let gap = EmptyBucket {
raw: self.raw,
idx: self.idx,
table: (),
};
@ -494,15 +475,14 @@ impl<K, V, M> EmptyBucket<K, V, M>
/// Use `make_hash` to construct a `SafeHash` to pass to this function.
pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
unsafe {
*self.raw.hash = hash.inspect();
ptr::write(self.raw.pair as *mut (K, V), (key, value));
*self.raw.hash() = hash.inspect();
ptr::write(self.raw.pair(), (key, value));
self.table.borrow_table_mut().size += 1;
}
FullBucket {
raw: self.raw,
idx: self.idx,
table: self.table,
}
}
@ -510,15 +490,14 @@ pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
/// Puts given key, remain value uninitialized.
/// It is only used for inplacement insertion.
pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
*self.raw.hash = hash.inspect();
let pair_mut = self.raw.pair as *mut (K, V);
ptr::write(&mut (*pair_mut).0, key);
*self.raw.hash() = hash.inspect();
let pair_ptr = self.raw.pair();
ptr::write(&mut (*pair_ptr).0, key);
self.table.borrow_table_mut().size += 1;
FullBucket {
raw: self.raw,
idx: self.idx,
table: self.table,
}
}
@ -536,7 +515,6 @@ pub fn next(self) -> Bucket<K, V, M> {
pub fn into_bucket(self) -> Bucket<K, V, M> {
Bucket {
raw: self.raw,
idx: self.idx,
table: self.table,
}
}
@ -546,7 +524,6 @@ pub fn into_bucket(self) -> Bucket<K, V, M> {
pub fn stash(self) -> FullBucket<K, V, Self> {
FullBucket {
raw: self.raw,
idx: self.idx,
table: self,
}
}
@ -560,17 +537,20 @@ pub fn displacement(&self) -> usize {
// Calculates the distance one has to travel when going from
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
// if the destination is not reached before the end of the table.
(self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1)
(self.raw.idx.wrapping_sub(self.hash().inspect() as usize)) & self.table.capacity_mask
}
#[inline]
pub fn hash(&self) -> SafeHash {
unsafe { SafeHash { hash: *self.raw.hash } }
unsafe { SafeHash { hash: *self.raw.hash() } }
}
/// Gets references to the key and value at a given index.
pub fn read(&self) -> (&K, &V) {
unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
unsafe {
let pair_ptr = self.raw.pair();
(&(*pair_ptr).0, &(*pair_ptr).1)
}
}
}
@ -586,11 +566,10 @@ pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
self.table.size -= 1;
unsafe {
*self.raw.hash = EMPTY_BUCKET;
let (k, v) = ptr::read(self.raw.pair);
*self.raw.hash() = EMPTY_BUCKET;
let (k, v) = ptr::read(self.raw.pair());
(EmptyBucket {
raw: self.raw,
idx: self.idx,
table: self.table,
},
k,
@ -604,9 +583,9 @@ pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
pub unsafe fn remove_key(&mut self) {
self.table.size -= 1;
*self.raw.hash = EMPTY_BUCKET;
let pair_mut = self.raw.pair as *mut (K, V);
ptr::drop_in_place(&mut (*pair_mut).0); // only drop key
*self.raw.hash() = EMPTY_BUCKET;
let pair_ptr = self.raw.pair();
ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key
}
}
@ -617,8 +596,8 @@ impl<K, V, M> FullBucket<K, V, M>
{
pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) {
unsafe {
let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h);
let (old_key, old_val) = ptr::replace(self.raw.pair as *mut (K, V), (k, v));
let old_hash = ptr::replace(self.raw.hash() as *mut SafeHash, h);
let (old_key, old_val) = ptr::replace(self.raw.pair(), (k, v));
(old_hash, old_key, old_val)
}
@ -630,8 +609,10 @@ impl<K, V, M> FullBucket<K, V, M>
{
/// Gets mutable references to the key and value at a given index.
pub fn read_mut(&mut self) -> (&mut K, &mut V) {
let pair_mut = self.raw.pair as *mut (K, V);
unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
unsafe {
let pair_ptr = self.raw.pair();
(&mut (*pair_ptr).0, &mut (*pair_ptr).1)
}
}
}
@ -644,7 +625,10 @@ impl<'t, K, V, M> FullBucket<K, V, M>
/// in exchange for this, the returned references have a longer lifetime
/// than the references returned by `read()`.
pub fn into_refs(self) -> (&'t K, &'t V) {
unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) }
unsafe {
let pair_ptr = self.raw.pair();
(&(*pair_ptr).0, &(*pair_ptr).1)
}
}
}
@ -654,8 +638,10 @@ impl<'t, K, V, M> FullBucket<K, V, M>
/// This works similarly to `into_refs`, exchanging a bucket state
/// for mutable references into the table.
pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
let pair_mut = self.raw.pair as *mut (K, V);
unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) }
unsafe {
let pair_ptr = self.raw.pair();
(&mut (*pair_ptr).0, &mut (*pair_ptr).1)
}
}
}
@ -667,22 +653,23 @@ pub fn full(&self) -> &FullBucket<K, V, M> {
&self.full
}
pub fn into_bucket(self) -> Bucket<K, V, M> {
self.full.into_bucket()
pub fn into_table(self) -> M {
self.full.into_table()
}
pub fn shift(mut self) -> Result<GapThenFull<K, V, M>, Bucket<K, V, M>> {
unsafe {
*self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
ptr::copy_nonoverlapping(self.full.raw.pair, self.gap.raw.pair as *mut (K, V), 1);
let (gap_hash, gap_pair) = self.gap.raw.hash_pair();
let (full_hash, full_pair) = self.full.raw.hash_pair();
*gap_hash = mem::replace(&mut *full_hash, EMPTY_BUCKET);
ptr::copy_nonoverlapping(full_pair, gap_pair, 1);
}
let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
let FullBucket { raw: prev_raw, .. } = self.full;
match self.full.next().peek() {
Full(bucket) => {
self.gap.raw = prev_raw;
self.gap.idx = prev_idx;
self.full = bucket;
@ -761,7 +748,7 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
if capacity == 0 {
return RawTable {
size: 0,
capacity: 0,
capacity_mask: capacity.wrapping_sub(1),
hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint),
marker: marker::PhantomData,
};
@ -801,25 +788,27 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
RawTable {
capacity: capacity,
capacity_mask: capacity.wrapping_sub(1),
size: 0,
hashes: TaggedHashUintPtr::new(hashes),
marker: marker::PhantomData,
}
}
fn first_bucket_raw(&self) -> RawBucket<K, V> {
let hashes_size = self.capacity * size_of::<HashUint>();
let pairs_size = self.capacity * size_of::<(K, V)>();
fn raw_bucket_at(&self, index: usize) -> RawBucket<K, V> {
let hashes_size = self.capacity() * size_of::<HashUint>();
let pairs_size = self.capacity() * size_of::<(K, V)>();
let buffer = self.hashes.ptr() as *mut u8;
let (pairs_offset, _, oflo) =
calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>());
debug_assert!(!oflo, "capacity overflow");
let buffer = self.hashes.ptr() as *mut u8;
unsafe {
RawBucket {
hash: self.hashes.ptr(),
pair: buffer.offset(pairs_offset as isize) as *const _,
hash_start: buffer as *mut HashUint,
pair_start: buffer.offset(pairs_offset as isize) as *const (K, V),
idx: index,
_marker: marker::PhantomData,
}
}
@ -837,7 +826,7 @@ pub fn new(capacity: usize) -> RawTable<K, V> {
/// The hashtable's capacity, similar to a vector's.
pub fn capacity(&self) -> usize {
self.capacity
self.capacity_mask.wrapping_add(1)
}
/// The number of elements ever `put` in the hashtable, minus the number
@ -848,8 +837,8 @@ pub fn size(&self) -> usize {
fn raw_buckets(&self) -> RawBuckets<K, V> {
RawBuckets {
raw: self.first_bucket_raw(),
hashes_end: unsafe { self.hashes.ptr().offset(self.capacity as isize) },
raw: self.raw_bucket_at(0),
elems_left: self.size,
marker: marker::PhantomData,
}
}
@ -857,25 +846,23 @@ fn raw_buckets(&self) -> RawBuckets<K, V> {
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.raw_buckets(),
elems_left: self.size(),
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
IterMut {
iter: self.raw_buckets(),
elems_left: self.size(),
_marker: marker::PhantomData,
}
}
pub fn into_iter(self) -> IntoIter<K, V> {
let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
// Replace the marker regardless of lifetime bounds on parameters.
IntoIter {
iter: RawBuckets {
raw: raw,
hashes_end: hashes_end,
elems_left: elems_left,
marker: marker::PhantomData,
},
table: self,
@ -883,12 +870,12 @@ pub fn into_iter(self) -> IntoIter<K, V> {
}
pub fn drain(&mut self) -> Drain<K, V> {
let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
let RawBuckets { raw, elems_left, .. } = self.raw_buckets();
// Replace the marker regardless of lifetime bounds on parameters.
Drain {
iter: RawBuckets {
raw: raw,
hashes_end: hashes_end,
elems_left: elems_left,
marker: marker::PhantomData,
},
table: unsafe { Shared::new(self) },
@ -900,18 +887,16 @@ pub fn drain(&mut self) -> Drain<K, V> {
/// state and should only be used for dropping the table's remaining
/// entries. It's used in the implementation of Drop.
unsafe fn rev_drop_buckets(&mut self) {
let first_raw = self.first_bucket_raw();
let mut raw = first_raw.offset(self.capacity as isize);
// initialize the raw bucket past the end of the table
let mut raw = self.raw_bucket_at(self.capacity());
let mut elems_left = self.size;
while elems_left != 0 {
debug_assert!(raw.hash != first_raw.hash);
raw.idx -= 1;
raw = raw.offset(-1);
if *raw.hash != EMPTY_BUCKET {
if *raw.hash() != EMPTY_BUCKET {
elems_left -= 1;
ptr::drop_in_place(raw.pair as *mut (K, V));
ptr::drop_in_place(raw.pair());
}
}
}
@ -931,7 +916,7 @@ pub fn tag(&self) -> bool {
/// this interface is safe, it's not used outside this module.
struct RawBuckets<'a, K, V> {
raw: RawBucket<K, V>,
hashes_end: *mut HashUint,
elems_left: usize,
// Strictly speaking, this should be &'a (K,V), but that would
// require that K:'a, and we often use RawBuckets<'static...> for
@ -946,7 +931,7 @@ impl<'a, K, V> Clone for RawBuckets<'a, K, V> {
fn clone(&self) -> RawBuckets<'a, K, V> {
RawBuckets {
raw: self.raw,
hashes_end: self.hashes_end,
elems_left: self.elems_left,
marker: marker::PhantomData,
}
}
@ -957,25 +942,36 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
type Item = RawBucket<K, V>;
fn next(&mut self) -> Option<RawBucket<K, V>> {
while self.raw.hash != self.hashes_end {
if self.elems_left == 0 {
return None;
}
loop {
unsafe {
// We are swapping out the pointer to a bucket and replacing
// it with the pointer to the next one.
let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
if *prev.hash != EMPTY_BUCKET {
return Some(prev);
let item = self.raw;
self.raw.idx += 1;
if *item.hash() != EMPTY_BUCKET {
self.elems_left -= 1;
return Some(item);
}
}
}
}
None
fn size_hint(&self) -> (usize, Option<usize>) {
(self.elems_left, Some(self.elems_left))
}
}
impl<'a, K, V> ExactSizeIterator for RawBuckets<'a, K, V> {
fn len(&self) -> usize {
self.elems_left
}
}
/// Iterator over shared references to entries in a table.
pub struct Iter<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
elems_left: usize,
}
unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {}
@ -986,16 +982,13 @@ impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter {
iter: self.iter.clone(),
elems_left: self.elems_left,
}
}
}
/// Iterator over mutable references to entries in a table.
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
elems_left: usize,
// To ensure invariance with respect to V
_marker: marker::PhantomData<&'a mut V>,
}
@ -1009,7 +1002,6 @@ impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> {
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.iter.clone(),
elems_left: self.elems_left,
}
}
}
@ -1027,7 +1019,6 @@ impl<K, V> IntoIter<K, V> {
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.iter.clone(),
elems_left: self.table.size,
}
}
}
@ -1044,11 +1035,8 @@ unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {}
impl<'a, K, V> Drain<'a, K, V> {
pub fn iter(&self) -> Iter<K, V> {
unsafe {
Iter {
iter: self.iter.clone(),
elems_left: (**self.table).size,
}
Iter {
iter: self.iter.clone(),
}
}
}
@ -1057,19 +1045,20 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.iter.next().map(|bucket| {
self.elems_left -= 1;
unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) }
self.iter.next().map(|raw| unsafe {
let pair_ptr = raw.pair();
(&(*pair_ptr).0, &(*pair_ptr).1)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.elems_left, Some(self.elems_left))
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
fn len(&self) -> usize {
self.elems_left
self.iter.len()
}
}
@ -1077,20 +1066,20 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
self.iter.next().map(|bucket| {
self.elems_left -= 1;
let pair_mut = bucket.pair as *mut (K, V);
unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) }
self.iter.next().map(|raw| unsafe {
let pair_ptr = raw.pair();
(&(*pair_ptr).0, &mut (*pair_ptr).1)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.elems_left, Some(self.elems_left))
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
fn len(&self) -> usize {
self.elems_left
self.iter.len()
}
}
@ -1098,23 +1087,23 @@ impl<K, V> Iterator for IntoIter<K, V> {
type Item = (SafeHash, K, V);
fn next(&mut self) -> Option<(SafeHash, K, V)> {
self.iter.next().map(|bucket| {
self.iter.next().map(|raw| {
self.table.size -= 1;
unsafe {
let (k, v) = ptr::read(bucket.pair);
(SafeHash { hash: *bucket.hash }, k, v)
let (k, v) = ptr::read(raw.pair());
(SafeHash { hash: *raw.hash() }, k, v)
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.table.size();
(size, Some(size))
self.iter.size_hint()
}
}
impl<K, V> ExactSizeIterator for IntoIter<K, V> {
fn len(&self) -> usize {
self.table.size()
self.iter().len()
}
}
@ -1123,23 +1112,21 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
#[inline]
fn next(&mut self) -> Option<(SafeHash, K, V)> {
self.iter.next().map(|bucket| {
unsafe {
(*self.table.as_mut_ptr()).size -= 1;
let (k, v) = ptr::read(bucket.pair);
(SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v)
}
self.iter.next().map(|raw| unsafe {
(*self.table.as_mut_ptr()).size -= 1;
let (k, v) = ptr::read(raw.pair());
(SafeHash { hash: ptr::replace(&mut *raw.hash(), EMPTY_BUCKET) }, k, v)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = unsafe { (**self.table).size() };
(size, Some(size))
self.iter.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
fn len(&self) -> usize {
unsafe { (**self.table).size() }
self.iter.len()
}
}
@ -1152,30 +1139,21 @@ fn drop(&mut self) {
impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
fn clone(&self) -> RawTable<K, V> {
unsafe {
let mut new_ht = RawTable::new_uninitialized(self.capacity());
let cap = self.capacity();
let mut new_ht = RawTable::new_uninitialized(cap);
{
let cap = self.capacity();
let mut new_buckets = Bucket::first(&mut new_ht);
let mut buckets = Bucket::first(self);
while buckets.index() != cap {
match buckets.peek() {
Full(full) => {
let (h, k, v) = {
let (k, v) = full.read();
(full.hash(), k.clone(), v.clone())
};
*new_buckets.raw.hash = h.inspect();
ptr::write(new_buckets.raw.pair as *mut (K, V), (k, v));
}
Empty(..) => {
*new_buckets.raw.hash = EMPTY_BUCKET;
}
}
new_buckets.next();
buckets.next();
let mut new_buckets = new_ht.raw_bucket_at(0);
let mut buckets = self.raw_bucket_at(0);
while buckets.idx < cap {
*new_buckets.hash() = *buckets.hash();
if *new_buckets.hash() != EMPTY_BUCKET {
let pair_ptr = buckets.pair();
let kv = ((*pair_ptr).0.clone(), (*pair_ptr).1.clone());
ptr::write(new_buckets.pair(), kv);
}
};
buckets.idx += 1;
new_buckets.idx += 1;
}
new_ht.size = self.size();
@ -1186,7 +1164,7 @@ fn clone(&self) -> RawTable<K, V> {
unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
fn drop(&mut self) {
if self.capacity == 0 {
if self.capacity() == 0 {
return;
}
@ -1202,8 +1180,8 @@ fn drop(&mut self) {
}
}
let hashes_size = self.capacity * size_of::<HashUint>();
let pairs_size = self.capacity * size_of::<(K, V)>();
let hashes_size = self.capacity() * size_of::<HashUint>();
let pairs_size = self.capacity() * size_of::<(K, V)>();
let (align, _, size, oflo) = calculate_allocation(hashes_size,
align_of::<HashUint>(),
pairs_size,

View File

@ -92,7 +92,7 @@ fn oom_handler() -> ! {
#[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))]
unsafe fn reset_sigpipe() {
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
}
#[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))]
unsafe fn reset_sigpipe() {}

View File

@ -4657,25 +4657,30 @@ pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> {
})
}
fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) {
match *visa {
Visibility::Inherited => (),
fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) {
if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) {
err.emit();
}
}
fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> {
match *vis {
Visibility::Inherited => Ok(()),
_ => {
let is_macro_rules: bool = match self.token {
token::Ident(sid) => sid.name == Symbol::intern("macro_rules"),
_ => false,
};
if is_macro_rules {
self.diagnostic().struct_span_err(span, "can't qualify macro_rules \
invocation with `pub`")
.help("did you mean #[macro_export]?")
.emit();
let mut err = self.diagnostic()
.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
err.help("did you mean #[macro_export]?");
Err(err)
} else {
self.diagnostic().struct_span_err(span, "can't qualify macro \
invocation with `pub`")
.help("try adjusting the macro to put `pub` \
inside the invocation")
.emit();
let mut err = self.diagnostic()
.struct_span_err(sp, "can't qualify macro invocation with `pub`");
err.help("try adjusting the macro to put `pub` inside the invocation");
Err(err)
}
}
}
@ -4686,14 +4691,36 @@ fn parse_impl_method(&mut self, vis: &Visibility)
-> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if self.token.is_path_start() {
// method macro.
// Method macro.
let prev_span = self.prev_span;
self.complain_if_pub_macro(&vis, prev_span);
// Before complaining about trying to set a macro as `pub`,
// check if `!` comes after the path.
let err = self.complain_if_pub_macro_diag(&vis, prev_span);
let lo = self.span;
let pth = self.parse_path(PathStyle::Mod)?;
self.expect(&token::Not)?;
let bang_err = self.expect(&token::Not);
if let Err(mut err) = err {
if let Err(mut bang_err) = bang_err {
// Given this code `pub path(`, it seems like this is not setting the
// visibility of a macro invocation, but rather a mistyped method declaration.
// Create a diagnostic pointing out that `fn` is missing.
//
// x | pub path(&self) {
// | ^ missing `fn` for method declaration
err.cancel();
bang_err.cancel();
// pub path(
// ^^ `sp` below will point to this
let sp = prev_span.between(self.prev_span);
err = self.diagnostic()
.struct_span_err(sp, "missing `fn` for method declaration");
err.span_label(sp, &"missing `fn`");
}
return Err(err);
}
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;

View File

@ -189,6 +189,30 @@ pub fn to(self, end: Span) -> Span {
Span { hi: end.hi, ..self }
}
}
pub fn between(self, end: Span) -> Span {
Span {
lo: self.hi,
hi: end.lo,
ctxt: if end.ctxt == SyntaxContext::empty() {
end.ctxt
} else {
self.ctxt
}
}
}
pub fn until(self, end: Span) -> Span {
Span {
lo: self.lo,
hi: end.lo,
ctxt: if end.ctxt == SyntaxContext::empty() {
end.ctxt
} else {
self.ctxt
}
}
}
}
#[derive(Clone, Debug)]

View File

@ -11,6 +11,6 @@
#![allow(dead_code)]
trait C {}
impl C { fn f() {} } //~ ERROR duplicate definitions with name `f`
impl C { fn f() {} }
impl C { fn f() {} }
fn main() { }

View File

@ -0,0 +1,10 @@
error[E0592]: duplicate definitions with name `f`
--> $DIR/coherence-overlapping-inherent-impl-trait.rs:14:10
|
14 | impl C { fn f() {} }
| ^^^^^^^^^ duplicate definitions for `f`
15 | impl C { fn f() {} }
| --------- other definition for `f`
error: aborting due to previous error

View File

@ -16,7 +16,7 @@
struct Foo;
impl Foo {
fn id() {} //~ ERROR duplicate definitions
fn id() {}
}
impl Foo {
@ -26,7 +26,7 @@ fn id() {}
struct Bar<T>(T);
impl<T> Bar<T> {
fn bar(&self) {} //~ ERROR duplicate definitions
fn bar(&self) {}
}
impl Bar<u32> {
@ -36,7 +36,7 @@ fn bar(&self) {}
struct Baz<T>(T);
impl<T: Copy> Baz<T> {
fn baz(&self) {} //~ ERROR duplicate definitions
fn baz(&self) {}
}
impl<T> Baz<Vec<T>> {

View File

@ -0,0 +1,29 @@
error[E0592]: duplicate definitions with name `id`
--> $DIR/overlapping_inherent_impls.rs:19:5
|
19 | fn id() {}
| ^^^^^^^^^^ duplicate definitions for `id`
...
23 | fn id() {}
| ---------- other definition for `id`
error[E0592]: duplicate definitions with name `bar`
--> $DIR/overlapping_inherent_impls.rs:29:5
|
29 | fn bar(&self) {}
| ^^^^^^^^^^^^^^^^ duplicate definitions for `bar`
...
33 | fn bar(&self) {}
| ---------------- other definition for `bar`
error[E0592]: duplicate definitions with name `baz`
--> $DIR/overlapping_inherent_impls.rs:39:5
|
39 | fn baz(&self) {}
| ^^^^^^^^^^^^^^^^ duplicate definitions for `baz`
...
43 | fn baz(&self) {}
| ---------------- other definition for `baz`
error: aborting due to 3 previous errors

View File

@ -0,0 +1,21 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct S;
impl S {
pub hello_method(&self) {
println!("Hello");
}
}
fn main() {
S.hello_method();
}

View File

@ -0,0 +1,8 @@
error: missing `fn` for method declaration
--> $DIR/issue-40006.rs:14:8
|
14 | pub hello_method(&self) {
| ^ missing `fn`
error: aborting due to previous error