Skip to content

Implement slicing syntax. #17318

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

Merged
merged 2 commits into from
Sep 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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