diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 717d2868abf98..6a5d015723d6c 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -278,6 +278,8 @@ pub use self::buffered::{BufReader, BufWriter, LineWriter};
 pub use self::cursor::Cursor;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::error::{Error, ErrorKind, Result};
+#[unstable(feature = "input", issue = "none")]
+pub use self::stdio::input;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index d6b7ad6254a8c..3a3127dba5594 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -5,7 +5,9 @@ use crate::io::prelude::*;
 use crate::cell::RefCell;
 use crate::fmt;
 use crate::io::lazy::Lazy;
-use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
+use crate::io::{
+    self, BufReader, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, LineWriter, Result, Write,
+};
 use crate::sync::{Arc, Mutex, MutexGuard, Once};
 use crate::sys::stdio;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
@@ -872,6 +874,44 @@ impl fmt::Debug for StderrLock<'_> {
     }
 }
 
+/// Prints the given `str` and reads a [`String`] from
+/// [standard input](Stdin). The trailing newline is stripped.
+/// Gives an error on EOF (end of file).
+///
+/// # Note
+///
+/// If you require more explicit control over capturing
+/// user input, see the [`Stdin::read_line`] method.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(input)]
+/// use std::io;
+///
+/// fn main() {
+///     let name = io::input("Enter name: ").expect("input failed!");
+///
+///     println!("Your name is {}!", name);
+/// }
+/// ```
+#[unstable(
+    feature = "input",
+    reason = "this function may be replaced with a more general mechanism",
+    issue = "none"
+)]
+pub fn input(prompt: &str) -> Result<String> {
+    let stdout = stdout();
+    let mut lock = stdout.lock();
+    lock.write_all(prompt.as_bytes())?;
+    lock.flush()?;
+    let mut input = String::new();
+    match stdin().read_line(&mut input)? {
+        0 => Err(Error::new(ErrorKind::UnexpectedEof, "input reached eof unexpectedly")),
+        _ => Ok(String::from(input.trim_end_matches(&['\n', '\r'][..]))),
+    }
+}
+
 /// Resets the thread-local stderr handle to the specified writer
 ///
 /// This will replace the current thread's stderr handle, returning the old
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index bd585d39c242f..83db285e142bd 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -274,6 +274,7 @@
 #![feature(global_asm)]
 #![feature(hash_raw_entry)]
 #![feature(hashmap_internals)]
+#![feature(input)]
 #![feature(int_error_internals)]
 #![feature(int_error_matching)]
 #![feature(into_future)]