Change:
cc
The rfc says It also includes an example which depends on usize: However RangeArgument only implements the first four. Furthermore as things stand it does not appear possible to accept RangeArgument<usizeand usize simultaneously, because dispatch doesn't consider the trait bound and reports that conflicting implementations exist.
Yes, was explicit about these issues. I forsee a new RFC to finish off drain and maybe the RangeArgument trait.
I believe this has

Discussion:
use rustc_unicode::str::Utf16Item; use borrow::{Cow, IntoCow}; <del> use str::{self, FromStr, Utf8Error}; </del> <ins> use range::RangeArgument; use str::{self, FromStr, Utf8Error, Chars}; </ins> use vec::{DerefVec, Vec, as_vec}; /// A growable string stored as a UTF-8 encoded buffer.

pub fn clear(&mut self) { self.vec.clear() } <ins> /// Create a draining iterator that removes the specified range in the string /// and yields the removed chars from start to end. The element range is /// removed even if the iterator is not consumed until the end. /// /// # Panics /// /// Panics if the starting point or end point are not on character boundaries, /// or if they are out of bounds. /// /// # Examples /// /// ``` /// # #![feature(collections_drain)] /// /// let mut s = String::from("α is alpha, β is beta"); /// let beta_offset = s.find('β').unwrap_or(s.len()); /// /// // Remove the range up until the β from the string /// let t: String = s.drain(..beta_offset).collect(); /// assert_eq!(t, "α is alpha, "); /// assert_eq!(s, "β is beta"); /// /// // A full range clears the string /// s.drain(..); /// assert_eq!(s, ""); /// ``` #[unstable(feature = "collections_drain", reason = "recently added, matches RFC")] pub fn drain<R>(&mut self, range: R) -> Drain where R: RangeArgument<usize> { // Memory safety // // The String version of Drain does not have the memory safety issues // of the vector version. The data is just plain bytes. // Because the range removal happens in Drop, if the Drain iterator is leaked, // the removal will not happen. let len = self.len(); let start = *range.start().unwrap_or(&0); let end = *range.end().unwrap_or(&len); // Take out two simultaneous borrows. The &mut String won't be accessed // until iteration is over, in Drop. let self_ptr = self as *mut _; // slicing does the appropriate bounds checks let chars_iter = self[start..end].chars(); Drain { start: start, end: end, iter: chars_iter, string: self_ptr, } } </ins> } impl FromUtf8Error {

Ok(()) } } <ins> /// A draining iterator for `String`. #[unstable(feature = "collections_drain", reason = "recently added")] pub struct Drain<'a> { /// Will be used as &'a mut String in the destructor string: *mut String, /// Start of part to remove start: usize, /// End of part to remove end: usize, /// Current remaining range to remove iter: Chars<'a>, } unsafe impl<'a> Sync for Drain<'a> {} unsafe impl<'a> Send for Drain<'a> {} #[unstable(feature = "collections_drain", reason = "recently added")] impl<'a> Drop for Drain<'a> { fn drop(&mut self) { unsafe { // Use Vec::drain. "Reaffirm" the bounds checks to avoid // panic code being inserted again. let self_vec = (*self.string).as_mut_vec(); if self.start <= self.end && self.end <= self_vec.len() { self_vec.drain(self.start..self.end); } } } } #[unstable(feature = "collections_drain", reason = "recently added")] impl<'a> Iterator for Drain<'a> { type Item = char; #[inline] fn next(&mut self) -> Option<char> { self.iter.next() } fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } } #[unstable(feature = "collections_drain", reason = "recently added")] impl<'a> DoubleEndedIterator for Drain<'a> { #[inline] fn next_back(&mut self) -> Option<char> { self.iter.next_back() } } </ins>

assert_eq!(s, d); } <ins> #[test] fn test_drain() { let mut s = String::from("αβγ"); assert_eq!(s.drain(2..4).collect::<String>(), "β"); assert_eq!(s, "αγ"); let mut t = String::from("abcd"); t.drain(..0); assert_eq!(t, "abcd"); t.drain(..1); assert_eq!(t, "bcd"); t.drain(3..); assert_eq!(t, "bcd"); t.drain(..); assert_eq!(t, ""); } </ins> #[bench] fn bench_with_capacity(b: &mut Bencher) { b.iter(|| {

} } <del> pub fn new_filemap(&self, filename: FileName, src: String) -> Rc<FileMap> { </del> <ins> pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> { </ins> let mut files = self.files.borrow_mut(); let start_pos = match files.last() { None => 0,

}; // Remove utf-8 BOM if any. <del> // FIXME #12884: no efficient/safe way to remove from the start of a string // and reuse the allocation. let mut src = if src.starts_with("u{feff}") { String::from(&src[3..]) } else { String::from(&src[..]) }; </del> <ins> if src.starts_with("u{feff}") { src.drain(..3); } </ins> // Append 'n' in case it's not already there. // This is a workaround to prevent CodeMap.lookup_filemap_idx from

#![feature(associated_consts)] #![feature(collections)] <ins> #![feature(collections_drain)] </ins> #![feature(core)] #![feature(libc)] #![feature(rustc_private)]

use collections::{BTreeMap, BTreeSet}; use collections::EnumSet; use collections::LinkedList; <ins> use collections::String; </ins> use collections::Vec; use collections::VecDeque; use collections::VecMap;

all_sync_send!(Vec::<usize>::new(), into_iter); is_sync_send!(Vec::<usize>::new(), drain(..)); <ins> is_sync_send!(String::new(), drain(..)); </ins> }