diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 92a94d23f08..36c67639101 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -15,7 +15,7 @@ #![feature(libc)] #![feature(path_ext)] #![feature(rustc_private)] -#![feature(slice_extras)] +#![feature(slice_splits)] #![feature(str_char)] #![feature(test)] #![feature(vec_push_all)] @@ -90,9 +90,7 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"), optflag("h", "help", "show this message")); - assert!(!args.is_empty()); - let argv0 = args[0].clone(); - let args_ = args.tail(); + let (argv0, args_) = args.split_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 d49463911e6..0933734ee38 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -282,34 +282,65 @@ impl [T] { /// Returns all but the first element of a slice. #[unstable(feature = "slice_extras", reason = "likely to be renamed")] + #[deprecated(since = "1.3.0", reason = "superseded by split_first")] #[inline] pub fn tail(&self) -> &[T] { core_slice::SliceExt::tail(self) } + /// Returns the first and all the rest of the elements of a slice. + #[unstable(feature = "slice_splits", reason = "new API")] + #[inline] + pub fn split_first(&self) -> Option<(&T, &[T])> { + core_slice::SliceExt::split_first(self) + } + /// Returns all but the first element of a mutable slice - #[unstable(feature = "slice_extras", - reason = "likely to be renamed or removed")] + #[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")] + #[deprecated(since = "1.3.0", reason = "superseded by split_first_mut")] #[inline] pub fn tail_mut(&mut self) -> &mut [T] { core_slice::SliceExt::tail_mut(self) } + /// Returns the first and all the rest of the elements of a slice. + #[unstable(feature = "slice_splits", reason = "new API")] + #[inline] + pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + core_slice::SliceExt::split_first_mut(self) + } + /// Returns all but the last element of a slice. #[unstable(feature = "slice_extras", reason = "likely to be renamed")] + #[deprecated(since = "1.3.0", reason = "superseded by split_last")] #[inline] pub fn init(&self) -> &[T] { core_slice::SliceExt::init(self) } + /// Returns the last and all the rest of the elements of a slice. + #[unstable(feature = "slice_splits", reason = "new API")] + #[inline] + pub fn split_last(&self) -> Option<(&T, &[T])> { + core_slice::SliceExt::split_last(self) + + } + /// Returns all but the last element of a mutable slice - #[unstable(feature = "slice_extras", - reason = "likely to be renamed or removed")] + #[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")] + #[deprecated(since = "1.3.0", reason = "superseded by split_last_mut")] #[inline] pub fn init_mut(&mut self) -> &mut [T] { core_slice::SliceExt::init_mut(self) } + /// Returns the last and all the rest of the elements of a slice. + #[unstable(feature = "slice_splits", since = "1.3.0")] + #[inline] + pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + core_slice::SliceExt::split_last_mut(self) + } + /// Returns the last element of a slice, or `None` if it is empty. /// /// # Examples diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 87c7449540c..6bf7380fdeb 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -36,7 +36,7 @@ #![feature(rustc_private)] #![feature(slice_bytes)] #![feature(slice_chars)] -#![feature(slice_extras)] +#![feature(slice_splits)] #![feature(slice_position_elem)] #![feature(split_off)] #![feature(step_by)] @@ -52,9 +52,10 @@ #![feature(vec_deque_retain)] #![feature(vec_from_raw_buf)] #![feature(vec_push_all)] -#![feature(vec_split_off)] #![feature(vecmap)] +#![allow(deprecated)] + #[macro_use] extern crate log; extern crate collections; diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index d88d8b8e4a0..d39abc63336 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -119,71 +119,48 @@ fn test_first_mut() { } #[test] -fn test_tail() { +fn test_split_first() { let mut a = vec![11]; let b: &[i32] = &[]; - assert_eq!(a.tail(), b); + assert!(b.split_first().is_none()); + assert_eq!(a.split_first(), Some((&11, b))); a = vec![11, 12]; let b: &[i32] = &[12]; - assert_eq!(a.tail(), b); + assert_eq!(a.split_first(), Some((&11, b))); } #[test] -fn test_tail_mut() { +fn test_split_first_mut() { let mut a = vec![11]; let b: &mut [i32] = &mut []; - assert!(a.tail_mut() == b); + assert!(b.split_first_mut().is_none()); + assert!(a.split_first_mut() == Some((&mut 11, b))); a = vec![11, 12]; let b: &mut [_] = &mut [12]; - assert!(a.tail_mut() == b); + assert!(a.split_first_mut() == Some((&mut 11, 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() { +fn test_split_last() { let mut a = vec![11]; let b: &[i32] = &[]; - assert_eq!(a.init(), b); + assert!(b.split_last().is_none()); + assert_eq!(a.split_last(), Some((&11, b))); a = vec![11, 12]; let b: &[_] = &[11]; - assert_eq!(a.init(), b); + assert_eq!(a.split_last(), Some((&12, b))); } #[test] -fn test_init_mut() { +fn test_split_last_mut() { let mut a = vec![11]; let b: &mut [i32] = &mut []; - assert!(a.init_mut() == b); + assert!(b.split_last_mut().is_none()); + assert!(a.split_last_mut() == Some((&mut 11, 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(); + assert!(a.split_last_mut() == Some((&mut 12, b))); } #[test] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 00e7ff3c4df..2c6acbf9157 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -83,6 +83,8 @@ pub trait SliceExt { 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 split_first<'a>(&'a self) -> Option<(&'a Self::Item, &'a [Self::Item])>; + fn split_last<'a>(&'a self) -> Option<(&'a Self::Item, &'a [Self::Item])>; fn last<'a>(&'a self) -> Option<&'a Self::Item>; unsafe fn get_unchecked<'a>(&'a self, index: usize) -> &'a Self::Item; fn as_ptr(&self) -> *const Self::Item; @@ -95,6 +97,8 @@ pub trait SliceExt { 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 split_first_mut<'a>(&'a mut self) -> Option<(&'a mut Self::Item, &'a mut [Self::Item])>; + fn split_last_mut<'a>(&'a mut self) -> Option<(&'a mut Self::Item, &'a mut [Self::Item])>; fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P> where P: FnMut(&Self::Item) -> bool; @@ -238,8 +242,17 @@ impl SliceExt for [T] { fn tail(&self) -> &[T] { &self[1..] } #[inline] - fn init(&self) -> &[T] { - &self[..self.len() - 1] + fn split_first(&self) -> Option<(&T, &[T])> { + if self.is_empty() { None } else { Some((&self[0], &self[1..])) } + } + + #[inline] + fn init(&self) -> &[T] { &self[..self.len() - 1] } + + #[inline] + fn split_last(&self) -> Option<(&T, &[T])> { + let len = self.len(); + if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) } } #[inline] @@ -328,8 +341,14 @@ impl SliceExt for [T] { } #[inline] - fn tail_mut(&mut self) -> &mut [T] { - &mut self[1 ..] + fn tail_mut(&mut self) -> &mut [T] { &mut self[1 ..] } + + #[inline] + fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { + if self.is_empty() { None } else { + let split = self.split_at_mut(1); + Some((&mut split.0[0], split.1)) + } } #[inline] @@ -338,6 +357,15 @@ impl SliceExt for [T] { &mut self[.. (len - 1)] } + #[inline] + fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { + let len = self.len(); + if len == 0 { None } else { + let split = self.split_at_mut(len - 1); + Some((&mut split.1[0], split.0)) + } + } + #[inline] fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool { SplitMut { v: self, pred: pred, finished: false } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 0d15f584d64..8ee0b10e174 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -56,7 +56,7 @@ //! optopt("o", "", "set output file name", "NAME"), //! optflag("h", "help", "print this help menu") //! ]; -//! let matches = match getopts(args.tail(), opts) { +//! let matches = match getopts(args[1..], opts) { //! Ok(m) => { m } //! Err(f) => { panic!(f.to_string()) } //! }; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 732b77a626e..f1984708b66 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -53,7 +53,7 @@ #![feature(rustc_private)] #![feature(scoped_tls)] #![feature(slice_bytes)] -#![feature(slice_extras)] +#![feature(slice_splits)] #![feature(slice_patterns)] #![feature(slice_position_elem)] #![feature(staged_api)] diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 5a79ef203b4..95fe2d87c94 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -688,7 +688,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).split_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 444192b7913..b7955290f91 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -696,12 +696,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![DUMMY_WILD_PAT; arity]; diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 8d226739e16..4a6cc019eb2 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1495,7 +1495,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(path.segments.split_last().unwrap().1); new_segs.push(new_seg); ast::Path { span: path.span, diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ad91f664af2..21f9e417acb 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -2571,7 +2571,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for &i in &ty_params { new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err; } - for &ty in fields.init() { + for &ty in fields.split_last().unwrap().1 { if ty.subst(tcx, &new_substs).references_error() { return Err(Unimplemented); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 30d5a4f111b..dd26fd25215 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -276,7 +276,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() + .split_last().unwrap().1 .iter().map(|ident| ident.identifier.name) .collect() } @@ -347,7 +347,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { continue; } }; - let module_path = module_path.init(); + let module_path = module_path.split_last().unwrap().1; (module_path.to_vec(), name) } }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0ec3979ccfb..1093d2ef318 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -23,7 +23,7 @@ #![feature(rc_weak)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] -#![feature(slice_extras)] +#![feature(slice_splits)] #![feature(staged_api)] #[macro_use] extern crate log; @@ -2881,7 +2881,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.split_last().unwrap().1.iter() .map(|ps| ps.identifier.name) .collect::>(); @@ -2939,7 +2939,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.split_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 ef3c858bed5..0f2506dc301 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1402,7 +1402,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, base_segments.last().unwrap(), &mut projection_bounds); - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS); trait_ref_to_object_type(this, rscope, span, @@ -1411,7 +1411,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS); ast_path_to_ty(this, rscope, span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 638cc868527..e6c79cfd30e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3668,7 +3668,7 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, Some((opt_self_ty, &path.segments, path_res.base_def)) } else { let mut def = path_res.base_def; - let ty_segments = path.segments.init(); + let ty_segments = path.segments.split_last().unwrap().1; let base_ty_end = path.segments.len() - path_res.depth; let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span, PathParamMode::Optional, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 7cf7d73a566..6083a2735c5 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -170,8 +170,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } // For DST, all intermediate types must be sized. - if !variant.fields.is_empty() { - for field in variant.fields.init() { + if let Some((_, fields)) = variant.fields.split_last() { + for field in fields { fcx.register_builtin_bound( field.ty, ty::BoundSized, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 8c3ef4ae631..4260791e384 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -85,7 +85,7 @@ This API is completely unstable and subject to change. #![feature(ref_slice)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] -#![feature(slice_extras)] +#![feature(slice_splits)] #![feature(staged_api)] #![feature(vec_push_all)] #![feature(cell_extras)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 17d912dd4cb..9ea22ced927 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -29,7 +29,6 @@ #![feature(path_relative_from)] #![feature(rustc_private)] #![feature(set_stdio)] -#![feature(slice_extras)] #![feature(slice_patterns)] #![feature(staged_api)] #![feature(subslice_offset)] @@ -192,7 +191,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 74c16127f41..72391ea51dd 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -353,7 +353,7 @@ pub fn unindent(s: &str) -> String { if !lines.is_empty() { let mut unindented = vec![ lines[0].trim().to_string() ]; - unindented.push_all(&lines.tail().iter().map(|&line| { + unindented.push_all(&lines[1..].iter().map(|&line| { if line.chars().all(|c| c.is_whitespace()) { line.to_string() } else { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 724c0b2a892..382b7495af5 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -44,7 +44,6 @@ #![feature(rt)] #![feature(rustc_private)] #![feature(set_stdio)] -#![feature(slice_extras)] #![feature(staged_api)] extern crate getopts; @@ -359,7 +358,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,