Skip to content

Commit 31a7e38

Browse files
committed
Implement slicing syntax.
`expr[]`, `expr[expr..]`, `expr[..expr]`,`expr[expr..expr]` Uses the Slice and SliceMut traits. Allows ... as well as .. in range patterns.
1 parent af3889f commit 31a7e38

27 files changed

+909
-105
lines changed

src/libcollections/vec.rs

+80
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use core::default::Default;
2020
use core::fmt;
2121
use core::mem;
2222
use core::num;
23+
use core::ops;
2324
use core::ptr;
2425
use core::raw::Slice as RawSlice;
2526
use core::uint;
@@ -464,6 +465,47 @@ impl<T> Index<uint,T> for Vec<T> {
464465
}
465466
}*/
466467

468+
impl<T> ops::Slice<uint, [T]> for Vec<T> {
469+
#[inline]
470+
fn as_slice_<'a>(&'a self) -> &'a [T] {
471+
self.as_slice()
472+
}
473+
474+
#[inline]
475+
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
476+
self.as_slice().slice_from_(start)
477+
}
478+
479+
#[inline]
480+
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
481+
self.as_slice().slice_to_(end)
482+
}
483+
#[inline]
484+
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
485+
self.as_slice().slice_(start, end)
486+
}
487+
}
488+
489+
impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
490+
#[inline]
491+
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
492+
self.as_mut_slice()
493+
}
494+
495+
#[inline]
496+
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
497+
self.as_mut_slice().slice_from_mut_(start)
498+
}
499+
500+
#[inline]
501+
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
502+
self.as_mut_slice().slice_to_mut_(end)
503+
}
504+
#[inline]
505+
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
506+
self.as_mut_slice().slice_mut_(start, end)
507+
}
508+
}
467509
impl<T> FromIterator<T> for Vec<T> {
468510
#[inline]
469511
fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
@@ -2327,6 +2369,44 @@ mod tests {
23272369
let _ = vec[3];
23282370
}
23292371

2372+
// NOTE uncomment after snapshot
2373+
/*
2374+
#[test]
2375+
#[should_fail]
2376+
fn test_slice_out_of_bounds_1() {
2377+
let x: Vec<int> = vec![1, 2, 3, 4, 5];
2378+
x[-1..];
2379+
}
2380+
2381+
#[test]
2382+
#[should_fail]
2383+
fn test_slice_out_of_bounds_2() {
2384+
let x: Vec<int> = vec![1, 2, 3, 4, 5];
2385+
x[..6];
2386+
}
2387+
2388+
#[test]
2389+
#[should_fail]
2390+
fn test_slice_out_of_bounds_3() {
2391+
let x: Vec<int> = vec![1, 2, 3, 4, 5];
2392+
x[-1..4];
2393+
}
2394+
2395+
#[test]
2396+
#[should_fail]
2397+
fn test_slice_out_of_bounds_4() {
2398+
let x: Vec<int> = vec![1, 2, 3, 4, 5];
2399+
x[1..6];
2400+
}
2401+
2402+
#[test]
2403+
#[should_fail]
2404+
fn test_slice_out_of_bounds_5() {
2405+
let x: Vec<int> = vec![1, 2, 3, 4, 5];
2406+
x[3..2];
2407+
}
2408+
*/
2409+
23302410
#[test]
23312411
fn test_swap_remove_empty() {
23322412
let mut vec: Vec<uint> = vec!();

src/libcore/ops.rs

+102-3
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
638638
* ```
639639
*/
640640
#[lang="index"]
641-
pub trait Index<Index,Result> {
641+
pub trait Index<Index, Result> {
642642
/// The method for the indexing (`Foo[Bar]`) operation
643643
fn index<'a>(&'a self, index: &Index) -> &'a Result;
644644
}
@@ -651,7 +651,7 @@ pub trait Index<Index,Result> {
651651
* # Example
652652
*
653653
* A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
654-
* calling `index`, and therefore, `main` prints `Indexing!`.
654+
* calling `index_mut`, and therefore, `main` prints `Indexing!`.
655655
*
656656
* ```
657657
* struct Foo;
@@ -669,11 +669,110 @@ pub trait Index<Index,Result> {
669669
* ```
670670
*/
671671
#[lang="index_mut"]
672-
pub trait IndexMut<Index,Result> {
672+
pub trait IndexMut<Index, Result> {
673673
/// The method for the indexing (`Foo[Bar]`) operation
674674
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
675675
}
676676

677+
/**
678+
*
679+
* The `Slice` trait is used to specify the functionality of slicing operations
680+
* like `arr[from..to]` when used in an immutable context.
681+
*
682+
* # Example
683+
*
684+
* A trivial implementation of `Slice`. When `Foo[..Foo]` happens, it ends up
685+
* calling `slice_to`, and therefore, `main` prints `Slicing!`.
686+
*
687+
* ```
688+
* struct Foo;
689+
*
690+
* impl ::core::ops::Slice<Foo, Foo> for Foo {
691+
* fn as_slice_<'a>(&'a self) -> &'a Foo {
692+
* println!("Slicing!");
693+
* self
694+
* }
695+
* fn slice_from_<'a>(&'a self, from: &Foo) -> &'a Foo {
696+
* println!("Slicing!");
697+
* self
698+
* }
699+
* fn slice_to_<'a>(&'a self, to: &Foo) -> &'a Foo {
700+
* println!("Slicing!");
701+
* self
702+
* }
703+
* fn slice_<'a>(&'a self, from: &Foo, to: &Foo) -> &'a Foo {
704+
* println!("Slicing!");
705+
* self
706+
* }
707+
* }
708+
*
709+
* fn main() {
710+
* Foo[..Foo];
711+
* }
712+
* ```
713+
*/
714+
// FIXME(#17273) remove the postscript _s
715+
#[lang="slice"]
716+
pub trait Slice<Idx, Sized? Result> for Sized? {
717+
/// The method for the slicing operation foo[]
718+
fn as_slice_<'a>(&'a self) -> &'a Result;
719+
/// The method for the slicing operation foo[from..]
720+
fn slice_from_<'a>(&'a self, from: &Idx) -> &'a Result;
721+
/// The method for the slicing operation foo[..to]
722+
fn slice_to_<'a>(&'a self, to: &Idx) -> &'a Result;
723+
/// The method for the slicing operation foo[from..to]
724+
fn slice_<'a>(&'a self, from: &Idx, to: &Idx) -> &'a Result;
725+
}
726+
727+
/**
728+
*
729+
* The `SliceMut` trait is used to specify the functionality of slicing
730+
* operations like `arr[from..to]`, when used in a mutable context.
731+
*
732+
* # Example
733+
*
734+
* A trivial implementation of `SliceMut`. When `Foo[Foo..]` happens, it ends up
735+
* calling `slice_from_mut`, and therefore, `main` prints `Slicing!`.
736+
*
737+
* ```
738+
* struct Foo;
739+
*
740+
* impl ::core::ops::SliceMut<Foo, Foo> for Foo {
741+
* fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
742+
* println!("Slicing!");
743+
* self
744+
* }
745+
* fn slice_from_mut_<'a>(&'a mut self, from: &Foo) -> &'a mut Foo {
746+
* println!("Slicing!");
747+
* self
748+
* }
749+
* fn slice_to_mut_<'a>(&'a mut self, to: &Foo) -> &'a mut Foo {
750+
* println!("Slicing!");
751+
* self
752+
* }
753+
* fn slice_mut_<'a>(&'a mut self, from: &Foo, to: &Foo) -> &'a mut Foo {
754+
* println!("Slicing!");
755+
* self
756+
* }
757+
* }
758+
*
759+
* fn main() {
760+
* Foo[mut Foo..];
761+
* }
762+
* ```
763+
*/
764+
// FIXME(#17273) remove the postscript _s
765+
#[lang="slice_mut"]
766+
pub trait SliceMut<Idx, Sized? Result> for Sized? {
767+
/// The method for the slicing operation foo[]
768+
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
769+
/// The method for the slicing operation foo[from..]
770+
fn slice_from_mut_<'a>(&'a mut self, from: &Idx) -> &'a mut Result;
771+
/// The method for the slicing operation foo[..to]
772+
fn slice_to_mut_<'a>(&'a mut self, to: &Idx) -> &'a mut Result;
773+
/// The method for the slicing operation foo[from..to]
774+
fn slice_mut_<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
775+
}
677776
/**
678777
*
679778
* The `Deref` trait is used to specify the functionality of dereferencing

src/libcore/slice.rs

+58
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use cmp;
4242
use default::Default;
4343
use iter::*;
4444
use num::{CheckedAdd, Saturating, div_rem};
45+
use ops;
4546
use option::{None, Option, Some};
4647
use ptr;
4748
use ptr::RawPtr;
@@ -475,6 +476,63 @@ impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
475476
}
476477
}
477478

479+
impl<T> ops::Slice<uint, [T]> for [T] {
480+
#[inline]
481+
fn as_slice_<'a>(&'a self) -> &'a [T] {
482+
self
483+
}
484+
485+
#[inline]
486+
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
487+
self.slice_(start, &self.len())
488+
}
489+
490+
#[inline]
491+
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
492+
self.slice_(&0, end)
493+
}
494+
#[inline]
495+
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
496+
assert!(*start <= *end);
497+
assert!(*end <= self.len());
498+
unsafe {
499+
transmute(RawSlice {
500+
data: self.as_ptr().offset(*start as int),
501+
len: (*end - *start)
502+
})
503+
}
504+
}
505+
}
506+
507+
impl<T> ops::SliceMut<uint, [T]> for [T] {
508+
#[inline]
509+
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
510+
self
511+
}
512+
513+
#[inline]
514+
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
515+
let len = &self.len();
516+
self.slice_mut_(start, len)
517+
}
518+
519+
#[inline]
520+
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
521+
self.slice_mut_(&0, end)
522+
}
523+
#[inline]
524+
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
525+
assert!(*start <= *end);
526+
assert!(*end <= self.len());
527+
unsafe {
528+
transmute(RawSlice {
529+
data: self.as_ptr().offset(*start as int),
530+
len: (*end - *start)
531+
})
532+
}
533+
}
534+
}
535+
478536
/// Extension methods for vectors such that their elements are
479537
/// mutable.
480538
#[experimental = "may merge with other traits; may lose region param; needs review"]

src/librustc/middle/cfg/construct.rs

+7
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
424424
self.call(expr, pred, &**l, Some(&**r).into_iter())
425425
}
426426

427+
ast::ExprSlice(ref base, ref start, ref end, _) => {
428+
self.call(expr,
429+
pred,
430+
&**base,
431+
start.iter().chain(end.iter()).map(|x| &**x))
432+
}
433+
427434
ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
428435
self.call(expr, pred, &**e, None::<ast::Expr>.iter())
429436
}

src/librustc/middle/expr_use_visitor.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
316316
ast::ExprPath(..) => { }
317317

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

332332
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
333-
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
333+
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
334334
self.select_from_expr(&**lhs);
335335
self.consume_expr(&**rhs);
336336
}
337337
}
338338

339+
ast::ExprSlice(ref base, ref start, ref end, _) => { // base[start..end]
340+
let args = match (start, end) {
341+
(&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
342+
(&Some(ref e), &None) => vec![&**e],
343+
(&None, &Some(ref e)) => vec![&**e],
344+
(&None, &None) => Vec::new()
345+
};
346+
let overloaded = self.walk_overloaded_operator(expr, &**base, args);
347+
assert!(overloaded);
348+
}
349+
339350
ast::ExprCall(ref callee, ref args) => { // callee(args)
340351
self.walk_callee(expr, &**callee);
341352
self.consume_exprs(args);
@@ -430,13 +441,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
430441
}
431442

432443
ast::ExprUnary(_, ref lhs) => {
433-
if !self.walk_overloaded_operator(expr, &**lhs, None) {
444+
if !self.walk_overloaded_operator(expr, &**lhs, Vec::new()) {
434445
self.consume_expr(&**lhs);
435446
}
436447
}
437448

438449
ast::ExprBinary(_, ref lhs, ref rhs) => {
439-
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
450+
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
440451
self.consume_expr(&**lhs);
441452
self.consume_expr(&**rhs);
442453
}
@@ -774,7 +785,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
774785
fn walk_overloaded_operator(&mut self,
775786
expr: &ast::Expr,
776787
receiver: &ast::Expr,
777-
rhs: Option<&ast::Expr>)
788+
rhs: Vec<&ast::Expr>)
778789
-> bool
779790
{
780791
if !self.typer.is_method_call(expr.id) {

src/librustc/middle/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ lets_do_this! {
247247
ShrTraitLangItem, "shr", shr_trait;
248248
IndexTraitLangItem, "index", index_trait;
249249
IndexMutTraitLangItem, "index_mut", index_mut_trait;
250+
SliceTraitLangItem, "slice", slice_trait;
251+
SliceMutTraitLangItem, "slice_mut", slice_mut_trait;
250252

251253
UnsafeTypeLangItem, "unsafe", unsafe_type;
252254

0 commit comments

Comments
 (0)