diff options
| author | bors <bors@rust-lang.org> | 2014-04-23 12:01:53 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-04-23 12:01:53 -0700 |
| commit | 6beb376b5c27c6b028092f227f865ba564fea17b (patch) | |
| tree | b52fa55b56bb4c1b21d1753c7d5c2402894d3c9b /src/libstd/str.rs | |
| parent | b5dd3f05fe95168b5569d0f519636149479eb6ac (diff) | |
| parent | 823c7eee6a040862abb5a5309693030394200e62 (diff) | |
| download | rust-6beb376b5c27c6b028092f227f865ba564fea17b.tar.gz rust-6beb376b5c27c6b028092f227f865ba564fea17b.zip | |
auto merge of #13686 : alexcrichton/rust/issue-12224, r=nikomatsakis
This alters the borrow checker's requirements on invoking closures from
requiring an immutable borrow to requiring a unique immutable borrow. This means
that it is illegal to invoke a closure through a `&` pointer because there is no
guarantee that is not aliased. This does not mean that a closure is required to
be in a mutable location, but rather a location which can be proven to be
unique (often through a mutable pointer).
For example, the following code is unsound and is no longer allowed:
type Fn<'a> = ||:'a;
fn call(f: |Fn|) {
f(|| {
f(|| {})
});
}
fn main() {
call(|a| {
a();
});
}
There is no replacement for this pattern. For all closures which are stored in
structures, it was previously allowed to invoke the closure through `&self` but
it now requires invocation through `&mut self`.
The standard library has a good number of violations of this new rule, but the
fixes will be separated into multiple breaking change commits.
Closes #12224
Diffstat (limited to 'src/libstd/str.rs')
| -rw-r--r-- | src/libstd/str.rs | 110 |
1 files changed, 60 insertions, 50 deletions
diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 9d91545bc12..99f1c66e702 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -217,7 +217,7 @@ impl<'a, S: Str> StrVector for Vec<S> { /// Something that can be used to compare against a character pub trait CharEq { /// Determine if the splitter should split at the given character - fn matches(&self, char) -> bool; + fn matches(&mut self, char) -> bool; /// Indicate if this is only concerned about ASCII characters, /// which can allow for a faster implementation. fn only_ascii(&self) -> bool; @@ -225,7 +225,7 @@ pub trait CharEq { impl CharEq for char { #[inline] - fn matches(&self, c: char) -> bool { *self == c } + fn matches(&mut self, c: char) -> bool { *self == c } #[inline] fn only_ascii(&self) -> bool { (*self as uint) < 128 } @@ -233,7 +233,7 @@ impl CharEq for char { impl<'a> CharEq for |char|: 'a -> bool { #[inline] - fn matches(&self, c: char) -> bool { (*self)(c) } + fn matches(&mut self, c: char) -> bool { (*self)(c) } #[inline] fn only_ascii(&self) -> bool { false } @@ -241,16 +241,16 @@ impl<'a> CharEq for |char|: 'a -> bool { impl CharEq for extern "Rust" fn(char) -> bool { #[inline] - fn matches(&self, c: char) -> bool { (*self)(c) } + fn matches(&mut self, c: char) -> bool { (*self)(c) } #[inline] fn only_ascii(&self) -> bool { false } } -impl<'a, C: CharEq> CharEq for &'a [C] { +impl<'a> CharEq for &'a [char] { #[inline] - fn matches(&self, c: char) -> bool { - self.iter().any(|m| m.matches(c)) + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&mut m| m.matches(c)) } #[inline] @@ -1981,11 +1981,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar") - /// assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar") - /// assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar") + /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar") + /// assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar") + /// assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar") /// ``` - fn trim_chars<C: CharEq>(&self, to_trim: &C) -> &'a str; + fn trim_chars<C: CharEq>(&self, to_trim: C) -> &'a str; /// Returns a string with leading `chars_to_trim` removed. /// @@ -1996,11 +1996,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11") - /// assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12") - /// assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123") + /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11") + /// assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12") + /// assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123") /// ``` - fn trim_left_chars<C: CharEq>(&self, to_trim: &C) -> &'a str; + fn trim_left_chars<C: CharEq>(&self, to_trim: C) -> &'a str; /// Returns a string with trailing `chars_to_trim` removed. /// @@ -2011,11 +2011,11 @@ pub trait StrSlice<'a> { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar") - /// assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar") - /// assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar") + /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar") + /// assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar") + /// assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar") /// ``` - fn trim_right_chars<C: CharEq>(&self, to_trim: &C) -> &'a str; + fn trim_right_chars<C: CharEq>(&self, to_trim: C) -> &'a str; /// Replace all occurrences of one string with another. /// @@ -2491,21 +2491,31 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn trim_left(&self) -> &'a str { - self.trim_left_chars(&char::is_whitespace) + self.trim_left_chars(char::is_whitespace) } #[inline] fn trim_right(&self) -> &'a str { - self.trim_right_chars(&char::is_whitespace) + self.trim_right_chars(char::is_whitespace) } #[inline] - fn trim_chars<C: CharEq>(&self, to_trim: &C) -> &'a str { - self.trim_left_chars(to_trim).trim_right_chars(to_trim) + fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str { + let cur = match self.find(|c: char| !to_trim.matches(c)) { + None => "", + Some(i) => unsafe { raw::slice_bytes(*self, i, self.len()) } + }; + match cur.rfind(|c: char| !to_trim.matches(c)) { + None => "", + Some(i) => { + let right = cur.char_range_at(i).next; + unsafe { raw::slice_bytes(cur, 0, right) } + } + } } #[inline] - fn trim_left_chars<C: CharEq>(&self, to_trim: &C) -> &'a str { + fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str { match self.find(|c: char| !to_trim.matches(c)) { None => "", Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) } @@ -2513,7 +2523,7 @@ impl<'a> StrSlice<'a> for &'a str { } #[inline] - fn trim_right_chars<C: CharEq>(&self, to_trim: &C) -> &'a str { + fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str { match self.rfind(|c: char| !to_trim.matches(c)) { None => "", Some(last) => { @@ -2631,7 +2641,7 @@ impl<'a> StrSlice<'a> for &'a str { unsafe { cast::transmute(*self) } } - fn find<C: CharEq>(&self, search: C) -> Option<uint> { + fn find<C: CharEq>(&self, mut search: C) -> Option<uint> { if search.only_ascii() { self.bytes().position(|b| search.matches(b as char)) } else { @@ -2642,7 +2652,7 @@ impl<'a> StrSlice<'a> for &'a str { } } - fn rfind<C: CharEq>(&self, search: C) -> Option<uint> { + fn rfind<C: CharEq>(&self, mut search: C) -> Option<uint> { if search.only_ascii() { self.bytes().rposition(|b| search.matches(b as char)) } else { @@ -3160,40 +3170,40 @@ mod tests { #[test] fn test_trim_left_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_left_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_left_chars(& &['*', ' ']), "foo *** "); - assert_eq!(" *** *** ".trim_left_chars(& &['*', ' ']), ""); - assert_eq!("foo *** ".trim_left_chars(& &['*', ' ']), "foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars(&['*', ' ']), "foo *** "); + assert_eq!(" *** *** ".trim_left_chars(&['*', ' ']), ""); + assert_eq!("foo *** ".trim_left_chars(&['*', ' ']), "foo *** "); - assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11"); - assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12"); - assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123"); + assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11"); + assert_eq!("12foo1bar12".trim_left_chars(&['1', '2']), "foo1bar12"); + assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123"); } #[test] fn test_trim_right_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_right_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_right_chars(& &['*', ' ']), " *** foo"); - assert_eq!(" *** *** ".trim_right_chars(& &['*', ' ']), ""); - assert_eq!(" *** foo".trim_right_chars(& &['*', ' ']), " *** foo"); + assert_eq!(" *** foo *** ".trim_right_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_right_chars(&['*', ' ']), " *** foo"); + assert_eq!(" *** *** ".trim_right_chars(&['*', ' ']), ""); + assert_eq!(" *** foo".trim_right_chars(&['*', ' ']), " *** foo"); - assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar"); - assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar"); - assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar"); + assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar"); + assert_eq!("12foo1bar12".trim_right_chars(&['1', '2']), "12foo1bar"); + assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar"); } #[test] fn test_trim_chars() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_chars(&v), " *** foo *** "); - assert_eq!(" *** foo *** ".trim_chars(& &['*', ' ']), "foo"); - assert_eq!(" *** *** ".trim_chars(& &['*', ' ']), ""); - assert_eq!("foo".trim_chars(& &['*', ' ']), "foo"); + assert_eq!(" *** foo *** ".trim_chars(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_chars(&['*', ' ']), "foo"); + assert_eq!(" *** *** ".trim_chars(&['*', ' ']), ""); + assert_eq!("foo".trim_chars(&['*', ' ']), "foo"); - assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar"); - assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar"); - assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar"); + assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar"); + assert_eq!("12foo1bar12".trim_chars(&['1', '2']), "foo1bar"); + assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar"); } #[test] @@ -4123,7 +4133,7 @@ mod bench { fn split_unicode_not_ascii(b: &mut Bencher) { struct NotAscii(char); impl CharEq for NotAscii { - fn matches(&self, c: char) -> bool { + fn matches(&mut self, c: char) -> bool { let NotAscii(cc) = *self; cc == c } @@ -4148,7 +4158,7 @@ mod bench { struct NotAscii(char); impl CharEq for NotAscii { #[inline] - fn matches(&self, c: char) -> bool { + fn matches(&mut self, c: char) -> bool { let NotAscii(cc) = *self; cc == c } |
