about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-03-15 21:16:04 +0000
committerbors <bors@rust-lang.org>2015-03-15 21:16:04 +0000
commitc62ae87db20cf070c5546f5aa814164d2445ec37 (patch)
treefa8658d0f9c77946d896eb91691f28dc4a25d114
parent542e2bb3910f8860d49b4b40bcd78d9c74e733ff (diff)
parent6e92f0580b0bfe8433df73a9139eaa72c47258b2 (diff)
Auto merge of #23206 - nagisa:print-io, r=alexcrichton
r? @alexcrichton or @aturon 

This still needs to somehow figure out how to avoid unstable warnings arising from the use of unstable functions. I tried to use `#[allow_internal_unstable]` but it still spits out warnings as far as I can see. @huonw (I think you implemented it) does `#[allow_internal_unstable]` not work for some reason or am I using it incorrectly?
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/libstd/io/mod.rs4
-rw-r--r--src/libstd/io/stdio.rs52
-rw-r--r--src/libstd/macros.rs15
-rw-r--r--src/libstd/old_io/stdio.rs14
-rw-r--r--src/libtest/lib.rs11
-rw-r--r--src/libtest/stats.rs19
8 files changed, 62 insertions, 57 deletions
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index e0261606ef1..e132e9833c1 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -37,7 +37,7 @@
 #![feature(staged_api)]
 #![feature(exit_status)]
 #![feature(io)]
-#![feature(set_panic)]
+#![feature(set_stdio)]
 
 extern crate arena;
 extern crate flate;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 152b6f5c80a..bd4177861dd 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -26,7 +26,7 @@
 #![feature(core)]
 #![feature(exit_status)]
 #![feature(int_uint)]
-#![feature(set_panic)]
+#![feature(set_stdio)]
 #![feature(libc)]
 #![feature(old_path)]
 #![feature(rustc_private)]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 821a0a0b06e..35ef375174a 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -33,10 +33,10 @@ pub use self::buffered::IntoInnerError;
 pub use self::cursor::Cursor;
 pub use self::error::{Result, Error, ErrorKind};
 pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
-pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr};
+pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr};
 pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
 #[doc(no_inline, hidden)]
-pub use self::stdio::set_panic;
+pub use self::stdio::{set_panic, set_print};
 
 #[macro_use] mod lazy;
 
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 0e68be8d9e2..75d047d5c9c 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -11,6 +11,7 @@
 use prelude::v1::*;
 use io::prelude::*;
 
+use cell::RefCell;
 use cmp;
 use fmt;
 use io::lazy::Lazy;
@@ -18,6 +19,13 @@ use io::{self, BufReader, LineWriter};
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 
+/// Stdout used by print! and println! macroses
+thread_local! {
+    static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
+        RefCell::new(None)
+    }
+}
+
 /// A handle to a raw instance of the standard input stream of this process.
 ///
 /// This handle is not synchronized or buffered in any fashion. Constructed via
@@ -338,15 +346,15 @@ impl<'a> Write for StderrLock<'a> {
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 
-/// Resets the task-local stdout handle to the specified writer
+/// Resets the task-local stderr handle to the specified writer
 ///
-/// This will replace the current task's stdout handle, returning the old
-/// handle. All future calls to `print` and friends will emit their output to
+/// This will replace the current task's stderr handle, returning the old
+/// handle. All future calls to `panic!` and friends will emit their output to
 /// this specified handle.
 ///
 /// Note that this does not need to be called for all new tasks; the default
-/// output handle is to the process's stdout stream.
-#[unstable(feature = "set_panic",
+/// output handle is to the process's stderr stream.
+#[unstable(feature = "set_stdio",
            reason = "this function may disappear completely or be replaced \
                      with a more general mechanism")]
 #[doc(hidden)]
@@ -360,3 +368,37 @@ pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
         Some(s)
     })
 }
+
+/// Resets the task-local stdout handle to the specified writer
+///
+/// This will replace the current task's stdout handle, returning the old
+/// handle. All future calls to `print!` and friends will emit their output to
+/// this specified handle.
+///
+/// Note that this does not need to be called for all new tasks; the default
+/// output handle is to the process's stdout stream.
+#[unstable(feature = "set_stdio",
+           reason = "this function may disappear completely or be replaced \
+                     with a more general mechanism")]
+#[doc(hidden)]
+pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+    use mem;
+    LOCAL_STDOUT.with(move |slot| {
+        mem::replace(&mut *slot.borrow_mut(), Some(sink))
+    }).and_then(|mut s| {
+        let _ = s.flush();
+        Some(s)
+    })
+}
+
+#[unstable(feature = "print",
+           reason = "implementation detail which may disappear or be replaced at any time")]
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+    if let Err(e) = LOCAL_STDOUT.with(|s| match s.borrow_mut().as_mut() {
+        Some(w) => w.write_fmt(args),
+        None => stdout().write_fmt(args)
+    }) {
+        panic!("failed printing to stdout: {}", e);
+    }
+}
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index a5022943267..7378f43f757 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -60,19 +60,21 @@ macro_rules! panic {
     });
 }
 
+/// Macro for printing to the standard output.
+///
 /// Equivalent to the `println!` macro except that a newline is not printed at
 /// the end of the message.
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
 macro_rules! print {
-    ($($arg:tt)*) => ($crate::old_io::stdio::print_args(format_args!($($arg)*)))
+    ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
 }
 
-/// Macro for printing to a task's stdout handle.
+/// Macro for printing to the standard output.
 ///
-/// Each task can override its stdout handle via `std::old_io::stdio::set_stdout`.
-/// The syntax of this macro is the same as that used for `format!`. For more
-/// information, see `std::fmt` and `std::old_io::stdio`.
+/// Use the `format!` syntax to write data to the standard output.
+/// See `std::fmt` for more information.
 ///
 /// # Examples
 ///
@@ -83,7 +85,8 @@ macro_rules! print {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! println {
-    ($($arg:tt)*) => ($crate::old_io::stdio::println_args(format_args!($($arg)*)))
+    ($fmt:expr) => (print!(concat!($fmt, "\n")));
+    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
 }
 
 /// Helper macro for unwrapping `Result` values while returning early with an
diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs
index 34b4ec94a44..dcc34505730 100644
--- a/src/libstd/old_io/stdio.rs
+++ b/src/libstd/old_io/stdio.rs
@@ -535,18 +535,4 @@ mod tests {
         stdout();
         stderr();
     }
-
-    #[test]
-    fn capture_stdout() {
-        use old_io::{ChanReader, ChanWriter};
-
-        let (tx, rx) = channel();
-        let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
-        // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-        let _t = thread::spawn(move|| {
-            set_stdout(Box::new(w));
-            println!("hello!");
-        });
-        assert_eq!(r.read_to_string().unwrap(), "hello!\n");
-    }
 }
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 3de24b1383f..8fe0cd6ebd4 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -39,13 +39,12 @@
 #![feature(collections)]
 #![feature(core)]
 #![feature(int_uint)]
-#![feature(old_io)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(std_misc)]
 #![feature(io)]
 #![feature(libc)]
-#![feature(set_panic)]
+#![feature(set_stdio)]
 
 extern crate getopts;
 extern crate serialize;
@@ -908,7 +907,6 @@ pub fn run_test(opts: &TestOpts,
         return;
     }
 
-    #[allow(deprecated)] // set_stdout
     fn run_test_inner(desc: TestDesc,
                       monitor_ch: Sender<MonitorMsg>,
                       nocapture: bool,
@@ -920,11 +918,6 @@ pub fn run_test(opts: &TestOpts,
             }
             fn flush(&mut self) -> io::Result<()> { Ok(()) }
         }
-        impl Writer for Sink {
-            fn write_all(&mut self, data: &[u8]) -> std::old_io::IoResult<()> {
-                Writer::write_all(&mut *self.0.lock().unwrap(), data)
-            }
-        }
 
         thread::spawn(move || {
             let data = Arc::new(Mutex::new(Vec::new()));
@@ -936,7 +929,7 @@ pub fn run_test(opts: &TestOpts,
 
             let result_guard = cfg.spawn(move || {
                 if !nocapture {
-                    std::old_io::stdio::set_stdout(box Sink(data2.clone()));
+                    io::set_print(box Sink(data2.clone()));
                     io::set_panic(box Sink(data2));
                 }
                 testfn.invoke(())
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index 42812e1e597..84d86c5746c 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -11,9 +11,6 @@
 #![allow(missing_docs)]
 
 use std::cmp::Ordering::{self, Less, Greater, Equal};
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::collections::hash_map;
-use std::hash::Hash;
 use std::mem;
 use std::num::{Float, FromPrimitive};
 
@@ -330,22 +327,6 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
     }
 }
 
-/// Returns a HashMap with the number of occurrences of every element in the
-/// sequence that the iterator exposes.
-#[cfg(not(stage0))]
-pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
-  where T: Iterator<Item=U>, U: Eq + Clone + Hash
-{
-    let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
-    for elem in iter {
-        match map.entry(elem) {
-            Occupied(mut entry) => { *entry.get_mut() += 1; },
-            Vacant(entry) => { entry.insert(1); },
-        }
-    }
-    map
-}
-
 // Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
 
 #[cfg(test)]