about summary refs log tree commit diff
path: root/src/libstd_unicode
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-08-12 15:31:37 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-08-13 21:07:03 -0700
commit742ca0caf25813ee30b70d9e29ab3eacb0076302 (patch)
tree53bbef3d12527ccc5a7f530a39f993e2e0709cfc /src/libstd_unicode
parentf3cf2062015200c0705ec2820dd02a7b9dc9bb22 (diff)
downloadrust-742ca0caf25813ee30b70d9e29ab3eacb0076302.tar.gz
rust-742ca0caf25813ee30b70d9e29ab3eacb0076302.zip
std: Respect formatting flags for str-like OsStr
Historically many `Display` and `Debug` implementations for `OsStr`-like
abstractions have gone through `String::from_utf8_lossy`, but this was updated
in #42613 to use an internal `Utf8Lossy` abstraction instead. This had the
unfortunate side effect of causing a regression (#43765) in code which relied on
these `fmt` trait implementations respecting the various formatting flags
specified.

This commit opportunistically adds back interpretation of formatting trait flags
in the "common case" where where `OsStr`-like "thing" is all valid utf-8 and can
delegate to the formatting implementation for `str`. This doesn't entirely solve
the regression as non-utf8 paths will format differently than they did before
still (in that they will not respect formatting flags), but this should solve
the regression for all "real world" use cases of paths and such. The door's also
still open for handling these flags in the future!

Closes #43765
Diffstat (limited to 'src/libstd_unicode')
-rw-r--r--src/libstd_unicode/lib.rs1
-rw-r--r--src/libstd_unicode/lossy.rs18
2 files changed, 16 insertions, 3 deletions
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index 698210e83f3..d568baa2cd7 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -34,7 +34,6 @@
 
 #![feature(core_char_ext)]
 #![feature(str_internals)]
-#![feature(core_intrinsics)]
 #![feature(decode_utf8)]
 #![feature(fused)]
 #![feature(fn_traits)]
diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs
index b914cbcf4b8..253dcb6a159 100644
--- a/src/libstd_unicode/lossy.rs
+++ b/src/libstd_unicode/lossy.rs
@@ -12,7 +12,7 @@ use core::str as core_str;
 use core::fmt;
 use core::fmt::Write;
 use char;
-use core::intrinsics;
+use core::mem;
 
 
 /// Lossy UTF-8 string.
@@ -27,7 +27,7 @@ impl Utf8Lossy {
     }
 
     pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
-        unsafe { intrinsics::transmute(bytes) }
+        unsafe { mem::transmute(bytes) }
     }
 
     pub fn chunks(&self) -> Utf8LossyChunksIter {
@@ -153,7 +153,21 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
 
 impl fmt::Display for Utf8Lossy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // If we're the empty string then our iterator won't actually yield
+        // anything, so perform the formatting manually
+        if self.bytes.len() == 0 {
+            return "".fmt(f)
+        }
+
         for Utf8LossyChunk { valid, broken } in self.chunks() {
+            // If we successfully decoded the whole chunk as a valid string then
+            // we can return a direct formatting of the string which will also
+            // respect various formatting flags if possible.
+            if valid.len() == self.bytes.len() {
+                assert!(broken.is_empty());
+                return valid.fmt(f)
+            }
+
             f.write_str(valid)?;
             if !broken.is_empty() {
                 f.write_char(char::REPLACEMENT_CHARACTER)?;