diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 79eaabe31e86b..8c14d1bbe8f8a 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -105,7 +105,7 @@ r##"
Switch tab
⏎
Go to active search result
- +
+ + / -
Collapse/expand all sections
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 88e1f780d0342..eb59c57603aae 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2498,7 +2498,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
if !foreign.is_empty() {
write!(w, "
- Fields");
+ sidebar.push_str(&format!("\
+ ", fields));
}
}
@@ -3633,40 +3635,122 @@ fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
Ok(())
}
+fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> {
+ match item.inner {
+ clean::ItemEnum::ImplItem(ref i) => {
+ if let Some(ref trait_) = i.trait_ {
+ Some((format!("{:#}", i.for_), format!("{:#}", trait_)))
+ } else {
+ None
+ }
+ },
+ _ => None,
+ }
+}
+
fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
t: &clean::Trait) -> fmt::Result {
let mut sidebar = String::new();
- let has_types = t.items.iter().any(|m| m.is_associated_type());
- let has_consts = t.items.iter().any(|m| m.is_associated_const());
- let has_required = t.items.iter().any(|m| m.is_ty_method());
- let has_provided = t.items.iter().any(|m| m.is_method());
+ let types = t.items
+ .iter()
+ .filter_map(|m| {
+ match m.name {
+ Some(ref name) if m.is_associated_type() => {
+ Some(format!("{name}",
+ name=name))
+ }
+ _ => None,
+ }
+ })
+ .collect::();
+ let consts = t.items
+ .iter()
+ .filter_map(|m| {
+ match m.name {
+ Some(ref name) if m.is_associated_const() => {
+ Some(format!("{name}",
+ name=name))
+ }
+ _ => None,
+ }
+ })
+ .collect::();
+ let required = t.items
+ .iter()
+ .filter_map(|m| {
+ match m.name {
+ Some(ref name) if m.is_ty_method() => {
+ Some(format!("{name}",
+ name=name))
+ }
+ _ => None,
+ }
+ })
+ .collect::();
+ let provided = t.items
+ .iter()
+ .filter_map(|m| {
+ match m.name {
+ Some(ref name) if m.is_method() => {
+ Some(format!("{name}", name=name))
+ }
+ _ => None,
+ }
+ })
+ .collect::();
- if has_types {
- sidebar.push_str("Associated Types");
+ if !types.is_empty() {
+ sidebar.push_str(&format!("",
+ types));
}
- if has_consts {
- sidebar.push_str("Associated Constants");
+ if !consts.is_empty() {
+ sidebar.push_str(&format!("",
+ consts));
}
- if has_required {
- sidebar.push_str("Required Methods");
+ if !required.is_empty() {
+ sidebar.push_str(&format!("",
+ required));
}
- if has_provided {
- sidebar.push_str("Provided Methods");
+ if !provided.is_empty() {
+ sidebar.push_str(&format!("",
+ provided));
}
let c = cache();
if let Some(implementors) = c.implementors.get(&it.def_id) {
- if implementors.iter().any(|i| i.impl_.for_.def_id()
- .map_or(false, |d| !c.paths.contains_key(&d)))
- {
- sidebar.push_str("\
- Implementations on Foreign Types");
- }
- }
-
- sidebar.push_str("Implementors");
+ let res = implementors.iter()
+ .filter(|i| i.impl_.for_.def_id()
+ .map_or(false, |d| !c.paths.contains_key(&d)))
+ .filter_map(|i| {
+ if let Some(item) = implementor2item(&c, i) {
+ match extract_for_impl_name(&item) {
+ Some((ref name, ref url)) => {
+ Some(format!("{}",
+ small_url_encode(url),
+ Escape(name)))
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }
+ })
+ .collect::();
+ if !res.is_empty() {
+ sidebar.push_str(&format!("",
+ res));
+ }
+ }
+
+ sidebar.push_str("");
sidebar.push_str(&sidebar_assoc_items(it));
@@ -3693,13 +3777,29 @@ fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item,
Ok(())
}
+fn get_struct_fields_name(fields: &[clean::Item]) -> String {
+ fields.iter()
+ .filter(|f| if let clean::StructFieldItem(..) = f.inner {
+ true
+ } else {
+ false
+ })
+ .filter_map(|f| match f.name {
+ Some(ref name) => Some(format!("\
+ {name}", name=name)),
+ _ => None,
+ })
+ .collect()
+}
+
fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item,
u: &clean::Union) -> fmt::Result {
let mut sidebar = String::new();
+ let fields = get_struct_fields_name(&u.fields);
- if u.fields.iter()
- .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) {
- sidebar.push_str("Fields");
+ if !fields.is_empty() {
+ sidebar.push_str(&format!("\
+ ", fields));
}
sidebar.push_str(&sidebar_assoc_items(it));
@@ -3714,8 +3814,16 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
e: &clean::Enum) -> fmt::Result {
let mut sidebar = String::new();
- if !e.variants.is_empty() {
- sidebar.push_str("Variants");
+ let variants = e.variants.iter()
+ .filter_map(|v| match v.name {
+ Some(ref name) => Some(format!("{name}\
+ ", name = name)),
+ _ => None,
+ })
+ .collect::();
+ if !variants.is_empty() {
+ sidebar.push_str(&format!("\
+ ", variants));
}
sidebar.push_str(&sidebar_assoc_items(it));
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index b1120e0af3894..1d9bfa260bf5b 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -213,6 +213,7 @@
break;
case "+":
+ case "-":
ev.preventDefault();
toggleAllDocs();
break;
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 398a692f8df5e..599b032b63030 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -582,13 +582,14 @@ body.blur > :not(#help) {
display: block;
margin-top: -1px;
}
-#help dd { margin: 5px 33px; }
+#help dd { margin: 5px 35px; }
#help .infos { padding-left: 0; }
#help h1, #help h2 { margin-top: 0; }
#help > div div {
width: 50%;
float: left;
padding: 20px;
+ padding-left: 17px;
}
.stab {
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index f81adad3ebebf..457c6e1409d3c 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -671,6 +671,10 @@ pub struct ArgsOs { inner: sys::args::Args }
/// set to arbitrary text, and may not even exist. This means this property should
/// not be relied upon for security purposes.
///
+/// On Unix systems shell usually expands unquoted arguments with glob patterns
+/// (such as `*` and `?`). On Windows this is not done, and such arguments are
+/// passed as-is.
+///
/// # Panics
///
/// The returned iterator will panic during iteration if any argument to the
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index d23cae40cfaff..15f858bca1643 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -20,7 +20,9 @@ use sys;
use sys_common::{FromInner, AsInner, AsInnerMut};
use sys::platform::fs::MetadataExt as UnixMetadataExt;
-/// Unix-specific extensions to `File`
+/// Unix-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
/// Reads a number of bytes starting from a given offset.
@@ -515,19 +517,79 @@ impl MetadataExt for fs::Metadata {
fn blocks(&self) -> u64 { self.st_blocks() }
}
-/// Add special unix types (block/char device, fifo and socket)
+/// Add support for special unix types (block/char device, fifo and socket).
#[stable(feature = "file_type_ext", since = "1.5.0")]
pub trait FileTypeExt {
/// Returns whether this file type is a block device.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::fs;
+ /// use std::os::unix::fs::FileTypeExt;
+ ///
+ /// # use std::io;
+ /// # fn f() -> io::Result<()> {
+ /// let meta = fs::metadata("block_device_file")?;
+ /// let file_type = meta.file_type();
+ /// assert!(file_type.is_block_device());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_block_device(&self) -> bool;
/// Returns whether this file type is a char device.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::fs;
+ /// use std::os::unix::fs::FileTypeExt;
+ ///
+ /// # use std::io;
+ /// # fn f() -> io::Result<()> {
+ /// let meta = fs::metadata("char_device_file")?;
+ /// let file_type = meta.file_type();
+ /// assert!(file_type.is_char_device());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_char_device(&self) -> bool;
/// Returns whether this file type is a fifo.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::fs;
+ /// use std::os::unix::fs::FileTypeExt;
+ ///
+ /// # use std::io;
+ /// # fn f() -> io::Result<()> {
+ /// let meta = fs::metadata("fifo_file")?;
+ /// let file_type = meta.file_type();
+ /// assert!(file_type.is_fifo());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_fifo(&self) -> bool;
/// Returns whether this file type is a socket.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::fs;
+ /// use std::os::unix::fs::FileTypeExt;
+ ///
+ /// # use std::io;
+ /// # fn f() -> io::Result<()> {
+ /// let meta = fs::metadata("unix.socket")?;
+ /// let file_type = meta.file_type();
+ /// assert!(file_type.is_socket());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "file_type_ext", since = "1.5.0")]
fn is_socket(&self) -> bool;
}
@@ -540,7 +602,9 @@ impl FileTypeExt for fs::FileType {
fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
}
-/// Unix-specific extension methods for `fs::DirEntry`
+/// Unix-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
pub trait DirEntryExt {
/// Returns the underlying `d_ino` field in the contained `dirent`
@@ -600,7 +664,9 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()>
}
#[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for unix-specific options.
+/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
pub trait DirBuilderExt {
/// Sets the mode to create new directories with. This option defaults to
/// 0o777.
diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs
new file mode 100644
index 0000000000000..9be40441e9d4f
--- /dev/null
+++ b/src/test/rustdoc/sidebar-items.rs
@@ -0,0 +1,59 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html
+// @has - '//*[@class="sidebar-title"][@href="#required-methods"]' 'Required Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+// @has - '//*[@class="sidebar-title"][@href="#provided-methods"]' 'Provided Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-title"][@href="#associated-const"]' 'Associated Constants'
+// @has - '//*[@class="sidebar-links"]/a' 'BAR'
+// @has - '//*[@class="sidebar-title"][@href="#associated-types"]' 'Associated Types'
+// @has - '//*[@class="sidebar-links"]/a' 'Output'
+pub trait Foo {
+ const BAR: u32 = 0;
+ type Output: ?Sized;
+
+ fn foo() {}
+ fn bar() -> Self::Output;
+}
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub struct Bar {
+ pub f: u32,
+ pub u: u32,
+ w: u32,
+}
+
+// @has foo/enum.En.html
+// @has - '//*[@class="sidebar-title"][@href="#variants"]' 'Variants'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+pub enum En {
+ foo,
+ bar,
+}
+
+// @has foo/union.MyUnion.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub union MyUnion {
+ pub f1: u32,
+ pub f2: f32,
+ w: u32,
+}