diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 770bca7524c..1dfae0ce83f 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -741,7 +741,9 @@ impl DoubleEndedIterator for Args {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Args {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("Args { .. }")
+        f.debug_struct("Args")
+            .field("inner", &self.inner.inner.inner_debug())
+            .finish()
     }
 }
 
@@ -766,7 +768,9 @@ impl DoubleEndedIterator for ArgsOs {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ArgsOs {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("ArgsOs { .. }")
+        f.debug_struct("ArgsOs")
+            .field("inner", &self.inner.inner_debug())
+            .finish()
     }
 }
 
@@ -1114,4 +1118,14 @@ mod tests {
                         r#""c:\te;st";c:\"#));
         assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
     }
+
+    #[test]
+    fn args_debug() {
+        assert_eq!(
+            format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()),
+            format!("{:?}", args()));
+        assert_eq!(
+            format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()),
+            format!("{:?}", args_os()));
     }
+}
diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs
index 212895d7b76..6e44ad705fe 100644
--- a/src/libstd/sys/redox/args.rs
+++ b/src/libstd/sys/redox/args.rs
@@ -35,6 +35,12 @@ pub struct Args {
     _dont_send_or_sync_me: PhantomData<*mut ()>,
 }
 
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        self.iter.as_slice()
+    }
+}
+
 impl Iterator for Args {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> { self.iter.next() }
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
index 6e35a472792..bbdcb5d3616 100644
--- a/src/libstd/sys/unix/args.rs
+++ b/src/libstd/sys/unix/args.rs
@@ -35,6 +35,12 @@ pub struct Args {
     _dont_send_or_sync_me: PhantomData<*mut ()>,
 }
 
+impl Args {
+    pub fn inner_debug(&self) -> &[OsString] {
+        self.iter.as_slice()
+    }
+}
+
 impl Iterator for Args {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> { self.iter.next() }
diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs
index aa61f9adb82..4784633edc1 100644
--- a/src/libstd/sys/windows/args.rs
+++ b/src/libstd/sys/windows/args.rs
@@ -16,6 +16,7 @@ use slice;
 use ops::Range;
 use ffi::OsString;
 use libc::{c_int, c_void};
+use fmt;
 
 pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }
 
@@ -39,6 +40,36 @@ pub struct Args {
     cur: *mut *mut u16,
 }
 
+pub struct ArgsInnerDebug<'a> {
+    args: &'a Args,
+}
+
+impl<'a> fmt::Debug for ArgsInnerDebug<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("[")?;
+        let mut first = true;
+        for i in self.args.range.clone() {
+            if !first {
+                f.write_str(", ")?;
+            }
+            first = false;
+
+            // Here we do allocation which could be avoided.
+            fmt::Debug::fmt(&unsafe { os_string_from_ptr(*self.args.cur.offset(i)) }, f)?;
+        }
+        f.write_str("]")?;
+        Ok(())
+    }
+}
+
+impl Args {
+    pub fn inner_debug(&self) -> ArgsInnerDebug {
+        ArgsInnerDebug {
+            args: self
+        }
+    }
+}
+
 unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
     let mut len = 0;
     while *ptr.offset(len) != 0 { len += 1; }