diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index f00ff9bcbe5e5..4862d60e4f165 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -89,8 +89,7 @@ pub fn parse_config(args: Vec ) -> Config { optflag("h", "help", "show this message")); assert!(!args.is_empty()); - let argv0 = args[0].clone(); - let args_ = args.tail(); + let (argv0, args_) = args.pop_first().unwrap(); if args[1] == "-h" || args[1] == "--help" { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); println!("{}", getopts::usage(&message, &groups)); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ff923fb19068f..a5ea9304c5e7f 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -460,20 +460,6 @@ impl [T] { core_slice::SliceExt::first(self) } - /// Returns all but the first element of a slice. - #[unstable(feature = "collections", reason = "likely to be renamed")] - #[inline] - pub fn tail(&self) -> &[T] { - core_slice::SliceExt::tail(self) - } - - /// Returns all but the last element of a slice. - #[unstable(feature = "collections", reason = "likely to be renamed")] - #[inline] - pub fn init(&self) -> &[T] { - core_slice::SliceExt::init(self) - } - /// Returns the last element of a slice, or `None` if it is empty. /// /// # Examples @@ -491,6 +477,42 @@ impl [T] { core_slice::SliceExt::last(self) } + /// Removes the first element of the slice and returns it, along with the + /// remainder, or `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.pop_first() == Some((&10, &[40, 30]))); + /// + /// let w: &[i32] = &[]; + /// assert!(w.pop_first() == None); + /// ``` + #[unstable(feature = "collections", reason = "brand new")] + #[inline] + pub fn pop_first(&self) -> Option<(&T, &[T])> { + core_slice::SliceExt::pop_first(self) + } + + /// Removes the last element of the slice and returns it, along with the + /// remainder, or `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// let v = [10, 40, 30]; + /// assert!(v.pop_last() == Some((&30, &[10, 40]))); + /// + /// let w: &[i32] = &[]; + /// assert!(w.pop_last() == None); + /// ``` + #[unstable(feature = "collections", reason = "brand new")] + #[inline] + pub fn pop_last(&self) -> Option<(&T, &[T])> { + core_slice::SliceExt::pop_last(self) + } + /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable(feature = "rust1", since = "1.0.0")] @@ -600,27 +622,27 @@ impl [T] { core_slice::SliceExt::first_mut(self) } - /// Returns all but the first element of a mutable slice - #[unstable(feature = "collections", - reason = "likely to be renamed or removed")] + /// Returns a mutable pointer to the last item in the slice. + #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn tail_mut(&mut self) -> &mut [T] { - core_slice::SliceExt::tail_mut(self) + pub fn last_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::last_mut(self) } - /// Returns all but the last element of a mutable slice - #[unstable(feature = "collections", - reason = "likely to be renamed or removed")] + /// Removes the first element from a mutable slice and returns it, along + /// with the remainder of the slice. + #[unstable(feature = "collections", reason = "brand new")] #[inline] - pub fn init_mut(&mut self) -> &mut [T] { - core_slice::SliceExt::init_mut(self) + pub fn pop_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + core_slice::SliceExt::pop_first_mut(self) } - /// Returns a mutable pointer to the last item in the slice. - #[stable(feature = "rust1", since = "1.0.0")] + /// Removes the last element from a mutable slice and returns it, along + /// with the remainder of the slice. + #[unstable(feature = "collections", reason = "brand new")] #[inline] - pub fn last_mut(&mut self) -> Option<&mut T> { - core_slice::SliceExt::last_mut(self) + pub fn pop_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + core_slice::SliceExt::pop_last_mut(self) } /// Returns an iterator over mutable subslices separated by elements that diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 5b0aceb76d19c..cfae7951c448b 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -118,74 +118,6 @@ fn test_first_mut() { assert_eq!(*a.first_mut().unwrap(), 11); } -#[test] -fn test_tail() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.tail(), b); - a = vec![11, 12]; - let b: &[i32] = &[12]; - assert_eq!(a.tail(), b); -} - -#[test] -fn test_tail_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.tail_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [12]; - assert!(a.tail_mut() == b); -} - -#[test] -#[should_panic] -fn test_tail_empty() { - let a = Vec::::new(); - a.tail(); -} - -#[test] -#[should_panic] -fn test_tail_mut_empty() { - let mut a = Vec::::new(); - a.tail_mut(); -} - -#[test] -fn test_init() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.init(), b); - a = vec![11, 12]; - let b: &[_] = &[11]; - assert_eq!(a.init(), b); -} - -#[test] -fn test_init_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.init_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [11]; - assert!(a.init_mut() == b); -} - -#[test] -#[should_panic] -fn test_init_empty() { - let a = Vec::::new(); - a.init(); -} - -#[test] -#[should_panic] -fn test_init_mut_empty() { - let mut a = Vec::::new(); - a.init_mut(); -} - #[test] fn test_last() { let mut a = vec![]; @@ -206,6 +138,46 @@ fn test_last_mut() { assert_eq!(*a.last_mut().unwrap(), 12); } +#[test] +fn test_pop_first() { + let a: &[i32] = &[]; + assert_eq!(a.pop_first(), None); + let b: &[i32] = &[11]; + assert_eq!(b.pop_first(), Some((&11, &[][..]))); + let c: &[i32] = &[11, 12]; + assert_eq!(c.pop_first(), Some((&11, &[12][..]))); +} + +#[test] +fn test_pop_first_mut() { + let a: &mut [i32] = &mut []; + assert_eq!(a.pop_first_mut(), None); + let b: &mut [i32] = &mut [11]; + assert_eq!(b.pop_first_mut(), Some((&mut 11, &mut [][..]))); + let c: &mut [i32] = &mut [11, 12]; + assert_eq!(c.pop_first_mut(), Some((&mut 11, &mut [12][..]))); +} + +#[test] +fn test_pop_last() { + let a: &[i32] = &[]; + assert_eq!(a.pop_last(), None); + let b: &[i32] = &[11]; + assert_eq!(b.pop_last(), Some((&11, &[][..]))); + let c: &[i32] = &[11, 12]; + assert_eq!(c.pop_last(), Some((&12, &[11][..]))); +} + +#[test] +fn test_pop_last_mut() { + let a: &mut [i32] = &mut []; + assert_eq!(a.pop_last_mut(), None); + let b: &mut [i32] = &mut [11]; + assert_eq!(b.pop_last_mut(), Some((&mut 11, &mut [][..]))); + let c: &mut [i32] = &mut [11, 12]; + assert_eq!(c.pop_last_mut(), Some((&mut 12, &mut [11][..]))); +} + #[test] fn test_slice() { // Test fixed length vector. diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 70e60adf64c2a..81094abeb60d8 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -78,9 +78,9 @@ pub trait SliceExt { fn chunks<'a>(&'a self, size: usize) -> Chunks<'a, Self::Item>; fn get<'a>(&'a self, index: usize) -> Option<&'a Self::Item>; fn first<'a>(&'a self) -> Option<&'a Self::Item>; - fn tail<'a>(&'a self) -> &'a [Self::Item]; - fn init<'a>(&'a self) -> &'a [Self::Item]; fn last<'a>(&'a self) -> Option<&'a Self::Item>; + fn pop_first(&self) -> Option<(&Self::Item, &[Self::Item])>; + fn pop_last(&self) -> Option<(&Self::Item, &[Self::Item])>; unsafe fn get_unchecked<'a>(&'a self, index: usize) -> &'a Self::Item; fn as_ptr(&self) -> *const Self::Item; fn binary_search_by(&self, f: F) -> Result where @@ -90,9 +90,9 @@ pub trait SliceExt { fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; - fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; - fn init_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; + fn pop_first_mut(&mut self) -> Option<(&mut Self::Item, &mut [Self::Item])>; + fn pop_last_mut(&mut self) -> Option<(&mut Self::Item, &mut [Self::Item])>; fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P> where P: FnMut(&Self::Item) -> bool; fn splitn_mut

(&mut self, n: usize, pred: P) -> SplitNMut @@ -207,16 +207,21 @@ impl SliceExt for [T] { } #[inline] - fn tail(&self) -> &[T] { &self[1..] } + fn last(&self) -> Option<&T> { + if self.len() == 0 { None } else { Some(&self[self.len() - 1]) } + } #[inline] - fn init(&self) -> &[T] { - &self[..self.len() - 1] + fn pop_first(&self) -> Option<(&T, &[T])> { + if self.len() == 0 { None } else { Some((&self[0], &self[1..])) } } #[inline] - fn last(&self) -> Option<&T> { - if self.len() == 0 { None } else { Some(&self[self.len() - 1]) } + fn pop_last(&self) -> Option<(&T, &[T])> { + match self.len() { + 0 => None, + n => Some((&self[n-1], &self[..(n-1)])) + } } #[inline] @@ -299,14 +304,24 @@ impl SliceExt for [T] { } #[inline] - fn tail_mut(&mut self) -> &mut [T] { - &mut self[1 ..] + fn pop_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + if self.len() == 0 { + None + } else { + let (head, tail) = self.split_at_mut(1); + Some((&mut head[0], tail)) + } } #[inline] - fn init_mut(&mut self) -> &mut [T] { - let len = self.len(); - &mut self[.. (len - 1)] + fn pop_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + match self.len() { + 0 => None, + n => { + let (init, last) = self.split_at_mut(n-1); + Some((&mut last[0], init)) + } + } } #[inline] diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index a659a93aef308..5ec886d706ab9 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -707,7 +707,7 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI -> csearch::FoundAst<'tcx> { debug!("Looking up item: {}", id); let item_doc = lookup_item(id, cdata.data()); - let path = item_path(item_doc).init().to_vec(); + let path = item_path(item_doc).pop_last().unwrap().1.to_vec(); match decode_inlined_item(cdata, tcx, path, item_doc) { Ok(ii) => csearch::FoundAst::Found(ii), Err(path) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 79f4d62b45e75..220cbc6375c96 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -693,12 +693,12 @@ fn is_useful(cx: &MatchCheckCtxt, Some(constructor) => { let matrix = rows.iter().filter_map(|r| { if pat_is_binding_or_wild(&cx.tcx.def_map, raw_pat(r[0])) { - Some(r.tail().to_vec()) + Some(r[1..].to_vec()) } else { None } }).collect(); - match is_useful(cx, &matrix, v.tail(), witness) { + match is_useful(cx, &matrix, &v[1..], witness) { UsefulWithWitness(pats) => { let arity = constructor_arity(cx, &constructor, left_ty); let wild_pats: Vec<_> = repeat(DUMMY_WILD_PAT).take(arity).collect(); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 36229a558e955..34247fccfb2a8 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1352,7 +1352,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { region_names, } = rebuild_info; - let last_seg = path.segments.last().unwrap(); + let (last_seg, init_seg) = path.segments.pop_last().unwrap(); let new_parameters = match last_seg.parameters { ast::ParenthesizedParameters(..) => { last_seg.parameters.clone() @@ -1409,7 +1409,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { parameters: new_parameters }; let mut new_segs = Vec::new(); - new_segs.push_all(path.segments.init()); + new_segs.push_all(init_seg); new_segs.push(new_seg); ast::Path { span: path.span, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 52db6013f4d5d..8bb4b2397f7c2 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -272,7 +272,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let module_path = match view_path.node { ViewPathSimple(_, ref full_path) => { full_path.segments - .init() + .pop_last().unwrap().1 .iter().map(|ident| ident.identifier.name) .collect() } @@ -334,8 +334,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { PathListIdent { name, .. } => (module_path.clone(), name.name), PathListMod { .. } => { - let name = match module_path.last() { - Some(name) => *name, + let (name, module_path) = match module_path.pop_last() { + Some((name, module_path)) => (*name, module_path), None => { self.resolve_error(source_item.span, "`self` import can only appear in an import list \ @@ -343,7 +343,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { continue; } }; - let module_path = module_path.init(); (module_path.to_vec(), name) } }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 045320e4fa425..2fa6dd0e782d1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2719,7 +2719,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = segments.init().iter() + let module_path = segments.pop_last().unwrap().1.iter() .map(|ps| ps.identifier.name) .collect::>(); @@ -2777,7 +2777,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = segments.init().iter() + let module_path = segments.pop_last().unwrap().1.iter() .map(|ps| ps.identifier.name) .collect::>(); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 939142cff1c32..47df2ad581778 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1239,15 +1239,16 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, // TyObjectSum, see that fn for details let mut projection_bounds = Vec::new(); + let (last_segment, init_segments) = base_segments.pop_last().unwrap(); let trait_ref = object_path_to_poly_trait_ref(this, rscope, span, param_mode, trait_def_id, - base_segments.last().unwrap(), + last_segment, &mut projection_bounds); - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + check_path_args(tcx, init_segments, NO_TPS | NO_REGIONS); trait_ref_to_object_type(this, rscope, span, @@ -1256,10 +1257,11 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + let (last_segment, init_segments) = base_segments.pop_last().unwrap(); + check_path_args(tcx, init_segments, NO_TPS | NO_REGIONS); ast_path_to_ty(this, rscope, span, param_mode, did, - base_segments.last().unwrap()) + last_segment) } def::DefTyParam(space, index, _, name) => { check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 156fbfede9c98..d393b93adb3a4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3347,7 +3347,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, scheme, &predicates, opt_self_ty, def, expr.span, id); } else { - let ty_segments = path.segments.init(); + let (method_segment, ty_segments) = path.segments.pop_last().unwrap(); let base_ty_end = path.segments.len() - path_res.depth; let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, @@ -3357,7 +3357,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, opt_self_ty, &ty_segments[..base_ty_end], &ty_segments[base_ty_end..]); - let method_segment = path.segments.last().unwrap(); let method_name = method_segment.identifier.name; match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { Ok((def, lp)) => { diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index eb06caf7d5a63..91b1cb3b6bdc1 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -174,8 +174,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } // For DST, all intermediate types must be sized. - if variant.fields.len() > 0 { - for field in variant.fields.init() { + if let Some((_, init_fields)) = variant.fields.pop_last() { + for field in init_fields { fcx.register_builtin_bound( field.ty, ty::BoundSized, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bdee53cd00964..e6abf9a153bed 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -192,7 +192,7 @@ pub fn usage(argv0: &str) { } pub fn main_args(args: &[String]) -> isize { - let matches = match getopts::getopts(args.tail(), &opts()) { + let matches = match getopts::getopts(&args[1..], &opts()) { Ok(m) => m, Err(err) => { println!("{}", err); diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 953b442bb3ceb..189b28403fc94 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -351,15 +351,16 @@ pub fn unindent(s: &str) -> String { }); if lines.len() >= 1 { - let mut unindented = vec![ lines[0].trim().to_string() ]; - unindented.push_all(&lines.tail().iter().map(|&line| { + let (first_line, tail_lines) = lines.pop_first().unwrap(); + let mut unindented = vec![ first_line.trim().to_string() ]; + unindented.extend(tail_lines.iter().map(|&line| { if line.chars().all(|c| c.is_whitespace()) { line.to_string() } else { assert!(line.len() >= min_indent); line[min_indent..].to_string() } - }).collect::>()); + })); unindented.connect("\n") } else { s.to_string() diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 397775fdbfec3..3990d7d23c52f 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -1081,7 +1081,7 @@ impl<'a> MethodDef<'a> { subpats.push(p); idents }; - for self_arg_name in self_arg_names.tail() { + for self_arg_name in &self_arg_names[1..] { let (p, idents) = mk_self_pat(cx, &self_arg_name[..]); subpats.push(p); self_pats_idents.push(idents); diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index c84703b93ed26..5ed93acfed46f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -364,7 +364,7 @@ Test Attributes: // Parses command line arguments into test options pub fn parse_opts(args: &[String]) -> Option { - let args_ = args.tail(); + let args_ = &args[1..]; let matches = match getopts::getopts(args_, &optgroups()) { Ok(m) => m,