Skip to content

Commit f1d3c6d

Browse files
committed
Move into_ascii_{low,upp}ercase (back) to a separate trait.
Implementing `AsciiExt` for `String` and `Vec<u8>` caused a regression: #32074 and the `where Self: Sized` hack to have the `into_` methods in that trait (which is also implemented for DST `str` and `[u8]`) was rather clunky. CC #27809
1 parent c116ae3 commit f1d3c6d

File tree

1 file changed

+53
-102
lines changed

1 file changed

+53
-102
lines changed

src/libstd/ascii.rs

Lines changed: 53 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -160,108 +160,6 @@ pub trait AsciiExt {
160160
/// ```
161161
#[unstable(feature = "ascii", issue = "27809")]
162162
fn make_ascii_lowercase(&mut self);
163-
164-
/// Converts this type to its ASCII upper case,
165-
/// consuming the value to avoid allocating memory where `to_ascii_uppercase` would.
166-
///
167-
/// See `to_ascii_uppercase` for more information.
168-
///
169-
/// # Examples
170-
///
171-
/// ```
172-
/// use std::ascii::AsciiExt;
173-
///
174-
/// let ascii: String = "a".to_owned();
175-
///
176-
/// let upper = ascii.into_ascii_uppercase();
177-
///
178-
/// assert_eq!(upper, "A");
179-
/// ```
180-
#[stable(feature = "into_ascii", since = "1.8.0")]
181-
fn into_ascii_uppercase(self) -> Self::Owned where Self: Sized {
182-
self.to_ascii_uppercase()
183-
}
184-
185-
/// Converts this type to its ASCII lower case,
186-
/// consuming the value to avoid allocating memory where `to_ascii_lowercase` would.
187-
///
188-
/// See `to_ascii_lowercase` for more information.
189-
///
190-
/// # Examples
191-
///
192-
/// ```
193-
/// use std::ascii::AsciiExt;
194-
///
195-
/// let ascii: String = "A".to_owned();
196-
///
197-
/// let lower = ascii.into_ascii_lowercase();
198-
///
199-
/// assert_eq!(lower, "a");
200-
/// ```
201-
#[stable(feature = "into_ascii", since = "1.8.0")]
202-
fn into_ascii_lowercase(self) -> Self::Owned where Self: Sized {
203-
self.to_ascii_lowercase()
204-
}
205-
}
206-
207-
/// Implement `into_ascii_lowercase` and `into_ascii_uppercase` without memory allocation,
208-
/// defer other methods to `str`.
209-
#[stable(feature = "into_ascii", since = "1.8.0")]
210-
impl AsciiExt for String {
211-
type Owned = Self;
212-
213-
#[inline] fn is_ascii(&self) -> bool { (**self).is_ascii() }
214-
#[inline] fn to_ascii_uppercase(&self) -> Self { (**self).to_ascii_uppercase() }
215-
#[inline] fn to_ascii_lowercase(&self) -> Self { (**self).to_ascii_lowercase() }
216-
#[inline] fn eq_ignore_ascii_case(&self, o: &Self) -> bool { (**self).eq_ignore_ascii_case(o) }
217-
#[inline] fn make_ascii_uppercase(&mut self) { (**self).make_ascii_uppercase() }
218-
#[inline] fn make_ascii_lowercase(&mut self) { (**self).make_ascii_lowercase() }
219-
220-
fn into_ascii_lowercase(mut self) -> Self {
221-
unsafe {
222-
for byte in self.as_mut_vec() {
223-
*byte = byte.to_ascii_lowercase()
224-
}
225-
}
226-
self
227-
}
228-
229-
fn into_ascii_uppercase(mut self) -> Self {
230-
unsafe {
231-
for byte in self.as_mut_vec() {
232-
*byte = byte.to_ascii_uppercase()
233-
}
234-
}
235-
self
236-
}
237-
}
238-
239-
/// Implement `into_ascii_lowercase` and `into_ascii_uppercase` without memory allocation,
240-
/// defer other methods to `[u8]`.
241-
#[stable(feature = "into_ascii", since = "1.8.0")]
242-
impl AsciiExt for Vec<u8> {
243-
type Owned = Self;
244-
245-
#[inline] fn is_ascii(&self) -> bool { (**self).is_ascii() }
246-
#[inline] fn to_ascii_uppercase(&self) -> Self { (**self).to_ascii_uppercase() }
247-
#[inline] fn to_ascii_lowercase(&self) -> Self { (**self).to_ascii_lowercase() }
248-
#[inline] fn eq_ignore_ascii_case(&self, o: &Self) -> bool { (**self).eq_ignore_ascii_case(o) }
249-
#[inline] fn make_ascii_uppercase(&mut self) { (**self).make_ascii_uppercase() }
250-
#[inline] fn make_ascii_lowercase(&mut self) { (**self).make_ascii_lowercase() }
251-
252-
fn into_ascii_lowercase(mut self) -> Self {
253-
for byte in &mut self {
254-
*byte = byte.to_ascii_lowercase()
255-
}
256-
self
257-
}
258-
259-
fn into_ascii_uppercase(mut self) -> Self {
260-
for byte in &mut self {
261-
*byte = byte.to_ascii_uppercase()
262-
}
263-
self
264-
}
265163
}
266164

267165
#[stable(feature = "rust1", since = "1.0.0")]
@@ -404,6 +302,52 @@ impl AsciiExt for char {
404302
fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
405303
}
406304

305+
/// Extension methods for ASCII-subset only operations on owned strings
306+
#[unstable(feature = "owned_ascii_ext", reason = "recently (re) added", issue = "27809")]
307+
pub trait OwnedAsciiExt {
308+
/// Converts the string to ASCII upper case:
309+
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
310+
/// but non-ASCII letters are unchanged.
311+
#[unstable(feature = "owned_ascii_ext", reason = "recently (re) added", issue = "27809")]
312+
fn into_ascii_uppercase(self) -> Self;
313+
314+
/// Converts the string to ASCII lower case:
315+
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
316+
/// but non-ASCII letters are unchanged.
317+
#[unstable(feature = "owned_ascii_ext", reason = "recently (re) added", issue = "27809")]
318+
fn into_ascii_lowercase(self) -> Self;
319+
}
320+
321+
#[unstable(feature = "owned_ascii_ext", reason = "recently (re) added", issue = "27809")]
322+
impl OwnedAsciiExt for String {
323+
#[inline]
324+
fn into_ascii_uppercase(self) -> String {
325+
// Vec<u8>::into_ascii_uppercase() preserves the UTF-8 invariant.
326+
unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_uppercase()) }
327+
}
328+
329+
#[inline]
330+
fn into_ascii_lowercase(self) -> String {
331+
// Vec<u8>::into_ascii_lowercase() preserves the UTF-8 invariant.
332+
unsafe { String::from_utf8_unchecked(self.into_bytes().into_ascii_lowercase()) }
333+
}
334+
}
335+
336+
#[unstable(feature = "owned_ascii_ext", reason = "recently (re) added", issue = "27809")]
337+
impl OwnedAsciiExt for Vec<u8> {
338+
#[inline]
339+
fn into_ascii_uppercase(mut self) -> Vec<u8> {
340+
self.make_ascii_uppercase();
341+
self
342+
}
343+
344+
#[inline]
345+
fn into_ascii_lowercase(mut self) -> Vec<u8> {
346+
self.make_ascii_lowercase();
347+
self
348+
}
349+
}
350+
407351
/// An iterator over the escaped version of a byte, constructed via
408352
/// `std::ascii::escape_default`.
409353
#[stable(feature = "rust1", since = "1.0.0")]
@@ -669,4 +613,11 @@ mod tests {
669613
&from_u32(lower).unwrap().to_string()));
670614
}
671615
}
616+
617+
#[test]
618+
/// https://github.com/rust-lang/rust/issues/32074
619+
fn test_issue_32074_regression() {
620+
let x = "a".to_string();
621+
assert!(x.eq_ignore_ascii_case("A"));
622+
}
672623
}

0 commit comments

Comments
 (0)