about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-11-05 11:42:59 +0000
committerbors <bors@rust-lang.org>2017-11-05 11:42:59 +0000
commit94ede93467beb4ac17956845607a7e8b226dda02 (patch)
treeefce44ea2cdc5c71fa03405dbd4bca2a4a20b99b /src/libstd
parent4efcc660f09ce3e83d194889f6d1161bf865f788 (diff)
parentea55596d5bc29708232a0bb232bf35d5e2e6cbce (diff)
Auto merge of #44042 - LukasKalbertodt:ascii-methods-on-instrinsics, r=alexcrichton
Copy all `AsciiExt` methods to the primitive types directly in order to deprecate it later

**EDIT:** [this PR is ready now](https://github.com/rust-lang/rust/pull/44042#issuecomment-333883548). I edited this post to reflect the current status of discussion, which is (apart from code review) pretty much settled.

---

This is my current progress in order to prepare stabilization of #39658. As discussed there (and in #39659), the idea is to deprecated `AsciiExt` and copy all methods to the type directly. Apparently there isn't really a reason to have those methods in an extension trait¹.

~~This is **work in progress**: copy&pasting code while slightly modifying the documentation isn't the most exciting thing to do. Therefore I wanted to already open this WIP PR after doing basically 1/4 of the job (copying methods to `&[u8]`, `char` and `&str` is still missing) to get some feedback before I continue. Some questions possibly worth discussing:~~

1. ~~Does everyone agree that deprecating `AsciiExt` is a good idea? Does everyone agree with the goal of this PR?~~ => apparently yes
2. ~~Are my changes OK so far? Did I do something wrong?~~
3. ~~The issue of the unstable-attribute is currently set to 0. I would wait until you say "Ok" to the whole thing, then create a tracking issue and then insert the correct issue id. Is that ok?~~
4. ~~I tweaked `eq_ignore_ascii_case()`: it now takes the argument `other: u8` instead of `other: &u8`. The latter was enforced by the trait. Since we're not bound to a trait anymore, we can drop the reference, ok?~~ => I reverted this, because the interface has to match the `AsciiExt` interface exactly.

¹ ~~Could it be that we can't write `impl [u8] {}`? This might be the reason for `AsciiExt`. If that is the case: is there a good reason we can't write such an impl block? What can we do instead?~~ => we couldn't at the time this PR was opened, but Simon made it possible.

/cc @SimonSapin @zackw
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/ascii.rs712
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/path.rs1
-rw-r--r--src/libstd/sys/windows/path.rs2
-rw-r--r--src/libstd/sys/windows/process.rs2
5 files changed, 114 insertions, 604 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 327deb9b419..96d719c528c 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -38,8 +38,8 @@ use iter::FusedIterator;
 /// ```
 /// use std::ascii::AsciiExt;
 ///
-/// assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
-/// assert_eq!("café".to_ascii_uppercase(), "CAFé");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
 /// ```
 ///
 /// In the first example, the lowercased string is represented `"cafe\u{301}"`
@@ -60,19 +60,10 @@ pub trait AsciiExt {
 
     /// Checks if the value is within the ASCII range.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// assert!(int_ascii.is_ascii());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
 
@@ -86,19 +77,10 @@ pub trait AsciiExt {
     /// To uppercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_uppercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
+    /// # Note
     ///
-    /// assert_eq!('A', ascii.to_ascii_uppercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
-    /// assert_eq!(65, int_ascii.to_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
@@ -115,19 +97,10 @@ pub trait AsciiExt {
     /// To lowercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_lowercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'A';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 65;
-    ///
-    /// assert_eq!('a', ascii.to_ascii_lowercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
-    /// assert_eq!(97, int_ascii.to_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
@@ -139,20 +112,10 @@ pub trait AsciiExt {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii1 = 'A';
-    /// let ascii2 = 'a';
-    /// let ascii3 = 'A';
-    /// let ascii4 = 'z';
+    /// # Note
     ///
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii2));
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
-    /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 
@@ -164,17 +127,10 @@ pub trait AsciiExt {
     /// To return a new uppercased value without modifying the existing one, use
     /// [`to_ascii_uppercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let mut ascii = 'a';
-    ///
-    /// ascii.make_ascii_uppercase();
-    ///
-    /// assert_eq!('A', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -188,17 +144,10 @@ pub trait AsciiExt {
     /// To return a new lowercased value without modifying the existing one, use
     /// [`to_ascii_lowercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
+    /// # Note
     ///
-    /// let mut ascii = 'A';
-    ///
-    /// ascii.make_ascii_lowercase();
-    ///
-    /// assert_eq!('a', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -209,32 +158,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphabetic.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(A.is_ascii_alphabetic());
-    /// assert!(G.is_ascii_alphabetic());
-    /// assert!(a.is_ascii_alphabetic());
-    /// assert!(g.is_ascii_alphabetic());
-    /// assert!(!zero.is_ascii_alphabetic());
-    /// assert!(!percent.is_ascii_alphabetic());
-    /// assert!(!space.is_ascii_alphabetic());
-    /// assert!(!lf.is_ascii_alphabetic());
-    /// assert!(!esc.is_ascii_alphabetic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
@@ -243,32 +170,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII uppercase.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_uppercase());
-    /// assert!(G.is_ascii_uppercase());
-    /// assert!(!a.is_ascii_uppercase());
-    /// assert!(!g.is_ascii_uppercase());
-    /// assert!(!zero.is_ascii_uppercase());
-    /// assert!(!percent.is_ascii_uppercase());
-    /// assert!(!space.is_ascii_uppercase());
-    /// assert!(!lf.is_ascii_uppercase());
-    /// assert!(!esc.is_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
@@ -277,32 +182,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII lowercase.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_lowercase());
-    /// assert!(!G.is_ascii_lowercase());
-    /// assert!(a.is_ascii_lowercase());
-    /// assert!(g.is_ascii_lowercase());
-    /// assert!(!zero.is_ascii_lowercase());
-    /// assert!(!percent.is_ascii_lowercase());
-    /// assert!(!space.is_ascii_lowercase());
-    /// assert!(!lf.is_ascii_lowercase());
-    /// assert!(!esc.is_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
@@ -312,32 +195,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphanumeric.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_alphanumeric());
-    /// assert!(G.is_ascii_alphanumeric());
-    /// assert!(a.is_ascii_alphanumeric());
-    /// assert!(g.is_ascii_alphanumeric());
-    /// assert!(zero.is_ascii_alphanumeric());
-    /// assert!(!percent.is_ascii_alphanumeric());
-    /// assert!(!space.is_ascii_alphanumeric());
-    /// assert!(!lf.is_ascii_alphanumeric());
-    /// assert!(!esc.is_ascii_alphanumeric());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
@@ -346,32 +207,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII digits.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_digit());
-    /// assert!(!G.is_ascii_digit());
-    /// assert!(!a.is_ascii_digit());
-    /// assert!(!g.is_ascii_digit());
-    /// assert!(zero.is_ascii_digit());
-    /// assert!(!percent.is_ascii_digit());
-    /// assert!(!space.is_ascii_digit());
-    /// assert!(!lf.is_ascii_digit());
-    /// assert!(!esc.is_ascii_digit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
@@ -381,32 +220,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII hex digits.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_hexdigit());
-    /// assert!(!G.is_ascii_hexdigit());
-    /// assert!(a.is_ascii_hexdigit());
-    /// assert!(!g.is_ascii_hexdigit());
-    /// assert!(zero.is_ascii_hexdigit());
-    /// assert!(!percent.is_ascii_hexdigit());
-    /// assert!(!space.is_ascii_hexdigit());
-    /// assert!(!lf.is_ascii_hexdigit());
-    /// assert!(!esc.is_ascii_hexdigit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
@@ -420,32 +237,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_punctuation());
-    /// assert!(!G.is_ascii_punctuation());
-    /// assert!(!a.is_ascii_punctuation());
-    /// assert!(!g.is_ascii_punctuation());
-    /// assert!(!zero.is_ascii_punctuation());
-    /// assert!(percent.is_ascii_punctuation());
-    /// assert!(!space.is_ascii_punctuation());
-    /// assert!(!lf.is_ascii_punctuation());
-    /// assert!(!esc.is_ascii_punctuation());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
@@ -454,32 +249,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_graphic());
-    /// assert!(G.is_ascii_graphic());
-    /// assert!(a.is_ascii_graphic());
-    /// assert!(g.is_ascii_graphic());
-    /// assert!(zero.is_ascii_graphic());
-    /// assert!(percent.is_ascii_graphic());
-    /// assert!(!space.is_ascii_graphic());
-    /// assert!(!lf.is_ascii_graphic());
-    /// assert!(!esc.is_ascii_graphic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
@@ -505,32 +278,10 @@ pub trait AsciiExt {
     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_whitespace());
-    /// assert!(!G.is_ascii_whitespace());
-    /// assert!(!a.is_ascii_whitespace());
-    /// assert!(!g.is_ascii_whitespace());
-    /// assert!(!zero.is_ascii_whitespace());
-    /// assert!(!percent.is_ascii_whitespace());
-    /// assert!(space.is_ascii_whitespace());
-    /// assert!(lf.is_ascii_whitespace());
-    /// assert!(!esc.is_ascii_whitespace());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
@@ -539,36 +290,18 @@ pub trait AsciiExt {
     /// Note that most ASCII whitespace characters are control
     /// characters, but SPACE is not.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(!A.is_ascii_control());
-    /// assert!(!G.is_ascii_control());
-    /// assert!(!a.is_ascii_control());
-    /// assert!(!g.is_ascii_control());
-    /// assert!(!zero.is_ascii_control());
-    /// assert!(!percent.is_ascii_control());
-    /// assert!(!space.is_ascii_control());
-    /// assert!(lf.is_ascii_control());
-    /// assert!(esc.is_ascii_control());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[str]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for str {
     type Owned = String;
@@ -660,6 +393,10 @@ impl AsciiExt for str {
     }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[u8]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
@@ -753,201 +490,77 @@ impl AsciiExt for [u8] {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for u8 {
-    type Owned = u8;
-    #[inline]
-    fn is_ascii(&self) -> bool { *self & 128 == 0 }
-    #[inline]
-    fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
-    #[inline]
-    fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+macro_rules! impl_by_delegating {
+    ($ty:ty, $owned:ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl AsciiExt for $ty {
+            type Owned = $owned;
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii(&self) -> bool { self.is_ascii() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_uppercase(&self) -> Self::Owned { self.to_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_lowercase(&self) -> Self::Owned { self.to_ascii_lowercase() }
 
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o) }
 
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_uppercase(&mut self) { self.make_ascii_uppercase(); }
 
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|Lx|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_lowercase(&mut self) { self.make_ascii_lowercase(); }
 
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Ux|U|Lx|L|D|P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Cw|W => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            C|Cw => true,
-            _ => false
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for char {
-    type Owned = char;
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        *self as u32 <= 0x7F
-    }
+            #[inline]
+            fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
 
-    #[inline]
-    fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_uppercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
 
-    #[inline]
-    fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_lowercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
 
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &char) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
+            #[inline]
+            fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
 
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+            #[inline]
+            fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphabetic()
-    }
+            #[inline]
+            fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_uppercase()
-    }
+            #[inline]
+            fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_lowercase()
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphanumeric()
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_digit()
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_hexdigit()
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_punctuation()
+            #[inline]
+            fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
+        }
     }
+}
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_graphic()
-    }
+impl_by_delegating!(u8, u8);
+impl_by_delegating!(char, char);
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_whitespace()
-    }
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `[u8]` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `[u8]`.
+#[cfg(not(stage0))]
+impl_by_delegating!([u8], Vec<u8>);
 
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_control()
-    }
-}
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `str` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `str`.
+#[cfg(not(stage0))]
+impl_by_delegating!(str, String);
 
 /// An iterator over the escaped version of a byte.
 ///
@@ -1066,112 +679,11 @@ impl fmt::Debug for EscapeDefault {
 }
 
 
-static ASCII_LOWERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@',
-
-          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z',
-
-                      b'[', b'\\', b']', b'^', b'_',
-    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-static ASCII_UPPERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
-    b'`',
-
-          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z',
-
-                      b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-enum AsciiCharacterClass {
-    C,  // control
-    Cw, // control whitespace
-    W,  // whitespace
-    D,  // digit
-    L,  // lowercase
-    Lx, // lowercase hex digit
-    U,  // uppercase
-    Ux, // uppercase hex digit
-    P,  // punctuation
-}
-use self::AsciiCharacterClass::*;
-
-static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
-//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
-    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
-    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
-    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
-    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
-    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
-    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
-    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
-    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
-];
-
 #[cfg(test)]
 mod tests {
-    use super::*;
+    //! Note that most of these tests are not testing `AsciiExt` methods, but
+    //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
+    //! just using those methods, though.
     use char::from_u32;
 
     #[test]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 5cf1d225b90..429153dc58b 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -244,6 +244,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(align_offset)]
 #![feature(array_error_internals)]
+#![feature(ascii_ctype)]
 #![feature(asm)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 294743ed2cc..270878dc029 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -77,7 +77,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use ascii::*;
 use borrow::{Borrow, Cow};
 use cmp;
 use error::Error;
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 2b47808451b..98d62a0c953 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
-
 use path::Prefix;
 use ffi::OsStr;
 use mem;
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 0d1766d5aec..631d69b05e1 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
+use ascii::AsciiExt;
 use collections::HashMap;
 use collections;
 use env::split_paths;