Skip to content
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

Rollup of 8 pull requests #57850

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
eed1407
Update std/lib.rs docs to reflect Rust 2018 usage
Xaeroxe Dec 28, 2018
13dc584
Merge visitors in AST validation
Zoxc Jan 18, 2019
a5d4aed
Address some comments
Zoxc Jan 19, 2019
b1f169f
Recover from parse errors in struct literal fields
estebank Jan 20, 2019
acbda76
Recover with suggestion from writing `.42` instead of `0.42`
estebank Jan 20, 2019
e387597
Reword message for incorrect float literal
estebank Jan 20, 2019
15bad8b
Extend incorrect float literal recovery to account for suffixes
estebank Jan 20, 2019
defa61f
Tweak field parse error recovery
estebank Jan 20, 2019
e33f7f7
Explain type mismatch cause pointing to return type when it is `impl …
estebank Jan 21, 2019
45a95b5
Use structured suggestion in stead of notes
estebank Jan 21, 2019
6c399d1
Add error for trailing angle brackets.
davidtwco Jan 21, 2019
3f0fc9b
Pluralize error messages.
davidtwco Jan 21, 2019
ab2479b
Move logic to its own method
estebank Jan 21, 2019
914d142
Extend trailing `>` detection for paths.
davidtwco Jan 21, 2019
4745b86
Accept more invalid code that is close to correct fields
estebank Jan 21, 2019
fb5d3c1
Stabilize Any::get_type_id and rename to type_id
SimonSapin Jan 22, 2019
4781c6f
Remove unused links
Xaeroxe Jan 22, 2019
40faae8
Add initial implementation of 'sort_at_index' for slices -- analog to…
Mokosha Jan 22, 2019
e32c45f
Rollup merge of #55448 - Mokosha:SortAtIndex, r=bluss
Centril Jan 23, 2019
051b5b3
Rollup merge of #57179 - Xaeroxe:patch-1, r=QuietMisdreavus
Centril Jan 23, 2019
8da08cf
Rollup merge of #57730 - Zoxc:combined-ast-validator, r=cramertj
Centril Jan 23, 2019
afc632b
Rollup merge of #57779 - estebank:recover-struct-fields, r=davidtwco
Centril Jan 23, 2019
cf308c5
Rollup merge of #57793 - estebank:impl-trait-resolve, r=oli-obk
Centril Jan 23, 2019
457420d
Rollup merge of #57795 - estebank:did-you-mean, r=zackmdavis
Centril Jan 23, 2019
9235c0f
Rollup merge of #57817 - davidtwco:issue-54521, r=estebank
Centril Jan 23, 2019
569fa82
Rollup merge of #57834 - SimonSapin:type_id, r=Centril
Centril Jan 23, 2019
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
16 changes: 6 additions & 10 deletions src/libcore/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,24 @@ pub trait Any: 'static {
/// # Examples
///
/// ```
/// #![feature(get_type_id)]
///
/// use std::any::{Any, TypeId};
///
/// fn is_string(s: &dyn Any) -> bool {
/// TypeId::of::<String>() == s.get_type_id()
/// TypeId::of::<String>() == s.type_id()
/// }
///
/// fn main() {
/// assert_eq!(is_string(&0), false);
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
/// }
/// ```
#[unstable(feature = "get_type_id",
reason = "this method will likely be replaced by an associated static",
issue = "27745")]
fn get_type_id(&self) -> TypeId;
#[stable(feature = "get_type_id", since = "1.34.0")]
fn type_id(&self) -> TypeId;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: 'static + ?Sized > Any for T {
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
fn type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -161,10 +157,10 @@ impl dyn Any {
let t = TypeId::of::<T>();

// Get TypeId of the type in the trait object
let boxed = self.get_type_id();
let concrete = self.type_id();

// Compare both TypeIds on equality
t == boxed
t == concrete
}

/// Returns some reference to the boxed value if it is of type `T`, or
Expand Down
147 changes: 147 additions & 0 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1582,6 +1582,153 @@ impl<T> [T] {
sort::quicksort(self, |a, b| f(a).lt(&f(b)));
}

/// Reorder the slice such that the element at `index` is at its final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
/// unstable (i.e. any number of equal elements may end up at position `index`), in-place
/// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth
/// element" in other libraries. It returns a triplet of the following values: all elements less
/// than the one at the given index, the value at the given index, and all elements greater than
/// the one at the given index.
///
/// # Current implementation
///
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
/// used for [`sort_unstable`].
///
/// [`sort_unstable`]: #method.sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
/// # Examples
///
/// ```
/// #![feature(slice_partition_at_index)]
///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Find the median
/// v.partition_at_index(2);
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
/// assert!(v == [-3, -5, 1, 2, 4] ||
/// v == [-5, -3, 1, 2, 4] ||
/// v == [-3, -5, 1, 4, 2] ||
/// v == [-5, -3, 1, 4, 2]);
/// ```
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
#[inline]
pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
where T: Ord
{
let mut f = |a: &T, b: &T| a.lt(b);
sort::partition_at_index(self, index, &mut f)
}

/// Reorder the slice with a comparator function such that the element at `index` is at its
/// final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the comparator function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
/// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
/// is also known as "kth element" in other libraries. It returns a triplet of the following
/// values: all elements less than the one at the given index, the value at the given index,
/// and all elements greater than the one at the given index, using the provided comparator
/// function.
///
/// # Current implementation
///
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
/// used for [`sort_unstable`].
///
/// [`sort_unstable`]: #method.sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
/// # Examples
///
/// ```
/// #![feature(slice_partition_at_index)]
///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Find the median as if the slice were sorted in descending order.
/// v.partition_at_index_by(2, |a, b| b.cmp(a));
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
/// assert!(v == [2, 4, 1, -5, -3] ||
/// v == [2, 4, 1, -3, -5] ||
/// v == [4, 2, 1, -5, -3] ||
/// v == [4, 2, 1, -3, -5]);
/// ```
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
#[inline]
pub fn partition_at_index_by<F>(&mut self, index: usize, mut compare: F)
-> (&mut [T], &mut T, &mut [T])
where F: FnMut(&T, &T) -> Ordering
{
let mut f = |a: &T, b: &T| compare(a, b) == Less;
sort::partition_at_index(self, index, &mut f)
}

/// Reorder the slice with a key extraction function such that the element at `index` is at its
/// final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the key extraction function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
/// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
/// is also known as "kth element" in other libraries. It returns a triplet of the following
/// values: all elements less than the one at the given index, the value at the given index, and
/// all elements greater than the one at the given index, using the provided key extraction
/// function.
///
/// # Current implementation
///
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
/// used for [`sort_unstable`].
///
/// [`sort_unstable`]: #method.sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
/// # Examples
///
/// ```
/// #![feature(slice_partition_at_index)]
///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Return the median as if the array were sorted according to absolute value.
/// v.partition_at_index_by_key(2, |a| a.abs());
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
/// assert!(v == [1, 2, -3, 4, -5] ||
/// v == [1, 2, -3, -5, 4] ||
/// v == [2, 1, -3, 4, -5] ||
/// v == [2, 1, -3, -5, 4]);
/// ```
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
#[inline]
pub fn partition_at_index_by_key<K, F>(&mut self, index: usize, mut f: F)
-> (&mut [T], &mut T, &mut [T])
where F: FnMut(&T) -> K, K: Ord
{
let mut g = |a: &T, b: &T| f(a).lt(&f(b));
sort::partition_at_index(self, index, &mut g)
}

/// Moves all consecutive repeated elements to the end of the slice according to the
/// [`PartialEq`] trait implementation.
///
Expand Down
89 changes: 89 additions & 0 deletions src/libcore/slice/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,3 +691,92 @@ pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)

recurse(v, &mut is_less, None, limit);
}

fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_less: &mut F
, mut pred: Option<&'a T>) where F: FnMut(&T, &T) -> bool
{
loop {
// For slices of up to this length it's probably faster to simply sort them.
const MAX_INSERTION: usize = 10;
if v.len() <= MAX_INSERTION {
insertion_sort(v, is_less);
return;
}

// Choose a pivot
let (pivot, _) = choose_pivot(v, is_less);

// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
// slice. Partition the slice into elements equal to and elements greater than the pivot.
// This case is usually hit when the slice contains many duplicate elements.
if let Some(p) = pred {
if !is_less(p, &v[pivot]) {
let mid = partition_equal(v, pivot, is_less);

// If we've passed our index, then we're good.
if mid > index {
return;
}

// Otherwise, continue sorting elements greater than the pivot.
v = &mut v[mid..];
index = index - mid;
pred = None;
continue;
}
}

let (mid, _) = partition(v, pivot, is_less);

// Split the slice into `left`, `pivot`, and `right`.
let (left, right) = {v}.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];

if mid < index {
v = right;
index = index - mid - 1;
pred = Some(pivot);
} else if mid > index {
v = left;
} else {
// If mid == index, then we're done, since partition() guaranteed that all elements
// after mid are greater than or equal to mid.
return;
}
}
}

pub fn partition_at_index<T, F>(v: &mut [T], index: usize, mut is_less: F)
-> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> bool
{
use cmp::Ordering::Less;
use cmp::Ordering::Greater;

if index >= v.len() {
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
}

if mem::size_of::<T>() == 0 {
// Sorting has no meaningful behavior on zero-sized types. Do nothing.
} else if index == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let (max_index, _) = v.iter().enumerate().max_by(
|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
v.swap(max_index, index);
} else if index == 0 {
// Find min element and place it in the first position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let (min_index, _) = v.iter().enumerate().min_by(
|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
v.swap(min_index, index);
} else {
partition_at_index_loop(v, index, &mut is_less, None);
}

let (left, right) = v.split_at_mut(index);
let (pivot, right) = right.split_at_mut(1);
let pivot = &mut pivot[0];
(left, pivot, right)
}
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#![feature(refcell_replace_swap)]
#![feature(slice_patterns)]
#![feature(sort_internals)]
#![feature(slice_partition_at_index)]
#![feature(specialization)]
#![feature(step_trait)]
#![feature(str_internals)]
Expand Down
Loading