Skip to content

Commit

Permalink
rollup merge of rust-lang#17318 : nick29581/slice
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Sep 19, 2014
2 parents b94075c + cf9c586 commit 81ee358
Show file tree
Hide file tree
Showing 29 changed files with 975 additions and 105 deletions.
80 changes: 80 additions & 0 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use core::default::Default;
use core::fmt;
use core::mem;
use core::num;
use core::ops;
use core::ptr;
use core::raw::Slice as RawSlice;
use core::uint;
Expand Down Expand Up @@ -464,6 +465,47 @@ impl<T> Index<uint,T> for Vec<T> {
}
}*/

impl<T> ops::Slice<uint, [T]> for Vec<T> {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a [T] {
self.as_slice()
}

#[inline]
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
self.as_slice().slice_from_(start)
}

#[inline]
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
self.as_slice().slice_to_(end)
}
#[inline]
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
self.as_slice().slice_(start, end)
}
}

impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
#[inline]
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
self.as_mut_slice()
}

#[inline]
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
self.as_mut_slice().slice_from_mut_(start)
}

#[inline]
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
self.as_mut_slice().slice_to_mut_(end)
}
#[inline]
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
self.as_mut_slice().slice_mut_(start, end)
}
}
impl<T> FromIterator<T> for Vec<T> {
#[inline]
fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
Expand Down Expand Up @@ -2327,6 +2369,44 @@ mod tests {
let _ = vec[3];
}

// NOTE uncomment after snapshot
/*
#[test]
#[should_fail]
fn test_slice_out_of_bounds_1() {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[-1..];
}
#[test]
#[should_fail]
fn test_slice_out_of_bounds_2() {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[..6];
}
#[test]
#[should_fail]
fn test_slice_out_of_bounds_3() {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[-1..4];
}
#[test]
#[should_fail]
fn test_slice_out_of_bounds_4() {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[1..6];
}
#[test]
#[should_fail]
fn test_slice_out_of_bounds_5() {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[3..2];
}
*/

#[test]
fn test_swap_remove_empty() {
let mut vec: Vec<uint> = vec!();
Expand Down
105 changes: 102 additions & 3 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
* ```
*/
#[lang="index"]
pub trait Index<Index,Result> {
pub trait Index<Index, Result> {
/// The method for the indexing (`Foo[Bar]`) operation
fn index<'a>(&'a self, index: &Index) -> &'a Result;
}
Expand All @@ -651,7 +651,7 @@ pub trait Index<Index,Result> {
* # Example
*
* A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
* calling `index`, and therefore, `main` prints `Indexing!`.
* calling `index_mut`, and therefore, `main` prints `Indexing!`.
*
* ```
* struct Foo;
Expand All @@ -669,11 +669,110 @@ pub trait Index<Index,Result> {
* ```
*/
#[lang="index_mut"]
pub trait IndexMut<Index,Result> {
pub trait IndexMut<Index, Result> {
/// The method for the indexing (`Foo[Bar]`) operation
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
}

/**
*
* The `Slice` trait is used to specify the functionality of slicing operations
* like `arr[from..to]` when used in an immutable context.
*
* # Example
*
* A trivial implementation of `Slice`. When `Foo[..Foo]` happens, it ends up
* calling `slice_to`, and therefore, `main` prints `Slicing!`.
*
* ```
* struct Foo;
*
* impl ::core::ops::Slice<Foo, Foo> for Foo {
* fn as_slice_<'a>(&'a self) -> &'a Foo {
* println!("Slicing!");
* self
* }
* fn slice_from_<'a>(&'a self, from: &Foo) -> &'a Foo {
* println!("Slicing!");
* self
* }
* fn slice_to_<'a>(&'a self, to: &Foo) -> &'a Foo {
* println!("Slicing!");
* self
* }
* fn slice_<'a>(&'a self, from: &Foo, to: &Foo) -> &'a Foo {
* println!("Slicing!");
* self
* }
* }
*
* fn main() {
* Foo[..Foo];
* }
* ```
*/
// FIXME(#17273) remove the postscript _s
#[lang="slice"]
pub trait Slice<Idx, Sized? Result> for Sized? {
/// The method for the slicing operation foo[]
fn as_slice_<'a>(&'a self) -> &'a Result;
/// The method for the slicing operation foo[from..]
fn slice_from_<'a>(&'a self, from: &Idx) -> &'a Result;
/// The method for the slicing operation foo[..to]
fn slice_to_<'a>(&'a self, to: &Idx) -> &'a Result;
/// The method for the slicing operation foo[from..to]
fn slice_<'a>(&'a self, from: &Idx, to: &Idx) -> &'a Result;
}

/**
*
* The `SliceMut` trait is used to specify the functionality of slicing
* operations like `arr[from..to]`, when used in a mutable context.
*
* # Example
*
* A trivial implementation of `SliceMut`. When `Foo[Foo..]` happens, it ends up
* calling `slice_from_mut`, and therefore, `main` prints `Slicing!`.
*
* ```
* struct Foo;
*
* impl ::core::ops::SliceMut<Foo, Foo> for Foo {
* fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
* println!("Slicing!");
* self
* }
* fn slice_from_mut_<'a>(&'a mut self, from: &Foo) -> &'a mut Foo {
* println!("Slicing!");
* self
* }
* fn slice_to_mut_<'a>(&'a mut self, to: &Foo) -> &'a mut Foo {
* println!("Slicing!");
* self
* }
* fn slice_mut_<'a>(&'a mut self, from: &Foo, to: &Foo) -> &'a mut Foo {
* println!("Slicing!");
* self
* }
* }
*
* fn main() {
* Foo[mut Foo..];
* }
* ```
*/
// FIXME(#17273) remove the postscript _s
#[lang="slice_mut"]
pub trait SliceMut<Idx, Sized? Result> for Sized? {
/// The method for the slicing operation foo[]
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
/// The method for the slicing operation foo[from..]
fn slice_from_mut_<'a>(&'a mut self, from: &Idx) -> &'a mut Result;
/// The method for the slicing operation foo[..to]
fn slice_to_mut_<'a>(&'a mut self, to: &Idx) -> &'a mut Result;
/// The method for the slicing operation foo[from..to]
fn slice_mut_<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
}
/**
*
* The `Deref` trait is used to specify the functionality of dereferencing
Expand Down
58 changes: 58 additions & 0 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use cmp;
use default::Default;
use iter::*;
use num::{CheckedAdd, Saturating, div_rem};
use ops;
use option::{None, Option, Some};
use ptr;
use ptr::RawPtr;
Expand Down Expand Up @@ -475,6 +476,63 @@ impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
}
}

impl<T> ops::Slice<uint, [T]> for [T] {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a [T] {
self
}

#[inline]
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
self.slice_(start, &self.len())
}

#[inline]
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
self.slice_(&0, end)
}
#[inline]
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
assert!(*start <= *end);
assert!(*end <= self.len());
unsafe {
transmute(RawSlice {
data: self.as_ptr().offset(*start as int),
len: (*end - *start)
})
}
}
}

impl<T> ops::SliceMut<uint, [T]> for [T] {
#[inline]
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
self
}

#[inline]
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
let len = &self.len();
self.slice_mut_(start, len)
}

#[inline]
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
self.slice_mut_(&0, end)
}
#[inline]
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
assert!(*start <= *end);
assert!(*end <= self.len());
unsafe {
transmute(RawSlice {
data: self.as_ptr().offset(*start as int),
len: (*end - *start)
})
}
}
}

/// Extension methods for vectors such that their elements are
/// mutable.
#[experimental = "may merge with other traits; may lose region param; needs review"]
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
self.call(expr, pred, &**l, Some(&**r).into_iter())
}

ast::ExprSlice(ref base, ref start, ref end, _) => {
self.call(expr,
pred,
&**base,
start.iter().chain(end.iter()).map(|x| &**x))
}

ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
self.call(expr, pred, &**e, None::<ast::Expr>.iter())
}
Expand Down
21 changes: 16 additions & 5 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
ast::ExprPath(..) => { }

ast::ExprUnary(ast::UnDeref, ref base) => { // *base
if !self.walk_overloaded_operator(expr, &**base, None) {
if !self.walk_overloaded_operator(expr, &**base, Vec::new()) {
self.select_from_expr(&**base);
}
}
Expand All @@ -330,12 +330,23 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
}

ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
self.select_from_expr(&**lhs);
self.consume_expr(&**rhs);
}
}

ast::ExprSlice(ref base, ref start, ref end, _) => { // base[start..end]
let args = match (start, end) {
(&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
(&Some(ref e), &None) => vec![&**e],
(&None, &Some(ref e)) => vec![&**e],
(&None, &None) => Vec::new()
};
let overloaded = self.walk_overloaded_operator(expr, &**base, args);
assert!(overloaded);
}

ast::ExprCall(ref callee, ref args) => { // callee(args)
self.walk_callee(expr, &**callee);
self.consume_exprs(args);
Expand Down Expand Up @@ -430,13 +441,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
}

ast::ExprUnary(_, ref lhs) => {
if !self.walk_overloaded_operator(expr, &**lhs, None) {
if !self.walk_overloaded_operator(expr, &**lhs, Vec::new()) {
self.consume_expr(&**lhs);
}
}

ast::ExprBinary(_, ref lhs, ref rhs) => {
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
self.consume_expr(&**lhs);
self.consume_expr(&**rhs);
}
Expand Down Expand Up @@ -774,7 +785,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
fn walk_overloaded_operator(&mut self,
expr: &ast::Expr,
receiver: &ast::Expr,
rhs: Option<&ast::Expr>)
rhs: Vec<&ast::Expr>)
-> bool
{
if !self.typer.is_method_call(expr.id) {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ lets_do_this! {
ShrTraitLangItem, "shr", shr_trait;
IndexTraitLangItem, "index", index_trait;
IndexMutTraitLangItem, "index_mut", index_mut_trait;
SliceTraitLangItem, "slice", slice_trait;
SliceMutTraitLangItem, "slice_mut", slice_mut_trait;

UnsafeTypeLangItem, "unsafe", unsafe_type;

Expand Down
Loading

0 comments on commit 81ee358

Please sign in to comment.