about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-26 15:17:32 +0000
committerbors <bors@rust-lang.org>2017-08-26 15:17:32 +0000
commit32f60560798a9cec098f13de3af0c350e6dc7485 (patch)
tree1478abfdd87ca6b6296355b02edf36860ac2f2cd
parent669d4770f2bac53a58bc9be0907f879b451be9b2 (diff)
parent502a11d53ed56aca9c35ae1c43117732cb221e16 (diff)
downloadrust-32f60560798a9cec098f13de3af0c350e6dc7485.tar.gz
rust-32f60560798a9cec098f13de3af0c350e6dc7485.zip
Auto merge of #44098 - frewsxcv:rollup, r=frewsxcv
Rollup of 7 pull requests

- Successful merges: #43776, #43966, #43979, #44072, #44086, #44090, #44091
- Failed merges:
-rw-r--r--src/etc/htmldocck.py33
-rw-r--r--src/liballoc/allocator.rs24
-rw-r--r--src/liballoc/boxed.rs2
-rw-r--r--src/liballoc/slice.rs18
-rw-r--r--src/liballoc/str.rs2
-rw-r--r--src/liballoc/string.rs3
-rw-r--r--src/libcore/cell.rs4
-rw-r--r--src/libcore/fmt/builders.rs10
-rw-r--r--src/libcore/mem.rs2
-rw-r--r--src/librustc_back/target/haiku_base.rs1
-rw-r--r--src/librustc_lint/unused.rs34
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/html/render.rs39
-rw-r--r--src/librustdoc/html/static/rustdoc.css4
-rw-r--r--src/librustdoc/html/static/styles/main.css6
-rw-r--r--src/libstd/io/mod.rs4
-rw-r--r--src/libstd/memchr.rs4
-rw-r--r--src/libstd/sys/redox/ext/mod.rs2
-rw-r--r--src/libstd/sys/unix/ext/mod.rs2
-rw-r--r--src/libstd/thread/mod.rs2
-rw-r--r--src/libsyntax/feature_gate.rs83
-rw-r--r--src/test/compile-fail/feature-gate-fn_must_use.rs31
-rw-r--r--src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs1
-rw-r--r--src/test/rustdoc/remove-duplicates.rs24
-rw-r--r--src/test/ui/lint/fn_must_use.rs1
-rw-r--r--src/test/ui/lint/fn_must_use.stderr12
26 files changed, 264 insertions, 88 deletions
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index a5449b748dd..7e8fde20346 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -29,7 +29,7 @@ showing the expected renderings.
 
 In order to avoid one-off dependencies for this task, this script uses
 a reasonably working HTML parser and the existing XPath implementation
-from Python 2's standard library. Hopefully we won't render
+from Python's standard library. Hopefully we won't render
 non-well-formed HTML.
 
 # Commands
@@ -110,11 +110,17 @@ import os.path
 import re
 import shlex
 from collections import namedtuple
-from HTMLParser import HTMLParser
+try:
+    from html.parser import HTMLParser
+except ImportError:
+    from HTMLParser import HTMLParser
 from xml.etree import cElementTree as ET
 
 # &larrb;/&rarrb; are not in HTML 4 but are in HTML 5
-from htmlentitydefs import entitydefs
+try:
+    from html.entities import entitydefs
+except ImportError:
+    from htmlentitydefs import entitydefs
 entitydefs['larrb'] = u'\u21e4'
 entitydefs['rarrb'] = u'\u21e5'
 entitydefs['nbsp'] = ' '
@@ -123,6 +129,11 @@ entitydefs['nbsp'] = ' '
 VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
                      'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
 
+# Python 2 -> 3 compatibility
+try:
+    unichr
+except NameError:
+    unichr = chr
 
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
@@ -184,12 +195,8 @@ def concat_multi_lines(f):
 
         # strip the common prefix from the current line if needed
         if lastline is not None:
-            maxprefix = 0
-            for i in xrange(min(len(line), len(lastline))):
-                if line[i] != lastline[i]:
-                    break
-                maxprefix += 1
-            line = line[maxprefix:].lstrip()
+            common_prefix = os.path.commonprefix([line, lastline])
+            line = line[len(common_prefix):].lstrip()
 
         firstlineno = firstlineno or lineno
         if line.endswith('\\'):
@@ -213,7 +220,7 @@ LINE_PATTERN = re.compile(r'''
 
 
 def get_commands(template):
-    with open(template, 'rUb') as f:
+    with open(template, 'rU') as f:
         for lineno, line in concat_multi_lines(f):
             m = LINE_PATTERN.search(line)
             if not m:
@@ -372,7 +379,7 @@ def check_command(c, cache):
                     cache.get_file(c.args[0])
                     ret = True
                 except FailedCheck as err:
-                    cerr = err.message
+                    cerr = str(err)
                     ret = False
             elif len(c.args) == 2: # @has/matches <path> <pat> = string test
                 cerr = "`PATTERN` did not match"
@@ -413,9 +420,9 @@ def check_command(c, cache):
 
     except FailedCheck as err:
         message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd)
-        print_err(c.lineno, c.context, err.message, message)
+        print_err(c.lineno, c.context, str(err), message)
     except InvalidCheck as err:
-        print_err(c.lineno, c.context, err.message)
+        print_err(c.lineno, c.context, str(err))
 
 def check(target, commands):
     cache = CachedFiles(target)
diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs
index fc6585a9f95..f14f2702324 100644
--- a/src/liballoc/allocator.rs
+++ b/src/liballoc/allocator.rs
@@ -110,7 +110,7 @@ impl Layout {
 
     /// Creates a layout, bypassing all checks.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe as it does not verify that `align` is
     /// a power-of-two that is also less than or equal to 2^31, nor
@@ -485,7 +485,7 @@ pub unsafe trait Alloc {
     /// behavior, e.g. to ensure initialization to particular sets of
     /// bit patterns.)
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure that `layout` has non-zero size.
@@ -513,7 +513,7 @@ pub unsafe trait Alloc {
 
     /// Deallocate the memory referenced by `ptr`.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -617,7 +617,7 @@ pub unsafe trait Alloc {
     /// behavior is well-defined (though underspecified) when this
     /// constraint is violated; further discussion below.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -688,7 +688,7 @@ pub unsafe trait Alloc {
     /// Behaves like `alloc`, but also ensures that the contents
     /// are set to zero before being returned.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -714,7 +714,7 @@ pub unsafe trait Alloc {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -736,7 +736,7 @@ pub unsafe trait Alloc {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `realloc` is.
     ///
@@ -770,7 +770,7 @@ pub unsafe trait Alloc {
     /// memory block referenced by `ptr` has not been transferred, and
     /// the contents of the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -827,7 +827,7 @@ pub unsafe trait Alloc {
     /// the memory block has not been transferred, and the contents of
     /// the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -920,7 +920,7 @@ pub unsafe trait Alloc {
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
@@ -993,7 +993,7 @@ pub unsafe trait Alloc {
     /// The returned block is suitable for passing to the
     /// `alloc`/`realloc` methods of this allocator.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -1037,7 +1037,7 @@ pub unsafe trait Alloc {
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index c0d43d9c527..82aac4dbf63 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -633,7 +633,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
 /// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
 /// closures become directly usable.)
 ///
-/// ### Example
+/// # Examples
 ///
 /// Here is a snippet of code which creates a hashmap full of boxed
 /// once closures and then removes them one by one, calling each
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index cbf242e884a..7787ace9441 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -171,7 +171,7 @@ mod hack {
 impl<T> [T] {
     /// Returns the number of elements in the slice.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -185,7 +185,7 @@ impl<T> [T] {
 
     /// Returns `true` if the slice has a length of 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -523,7 +523,7 @@ impl<T> [T] {
 
     /// Reverses the order of elements in the slice, in place.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut v = [1, 2, 3];
@@ -580,7 +580,7 @@ impl<T> [T] {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['r', 'u', 's', 't'];
@@ -613,7 +613,7 @@ impl<T> [T] {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
@@ -1040,7 +1040,7 @@ impl<T> [T] {
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1074,7 +1074,7 @@ impl<T> [T] {
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1419,7 +1419,7 @@ impl<T> [T] {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
@@ -1445,7 +1445,7 @@ impl<T> [T] {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 80317cd763b..79b2bbce2af 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -1714,7 +1714,7 @@ impl str {
     ///
     /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Basic usage
     ///
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 96bd6273c94..b1919c7c968 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -82,7 +82,7 @@ use boxed::Box;
 ///
 /// # Examples
 ///
-/// You can create a `String` from a literal string with `String::from`:
+/// You can create a `String` from a literal string with [`String::from`]:
 ///
 /// ```
 /// let hello = String::from("Hello, world!");
@@ -98,6 +98,7 @@ use boxed::Box;
 /// hello.push_str("orld!");
 /// ```
 ///
+/// [`String::from`]: #method.from
 /// [`char`]: ../../std/primitive.char.html
 /// [`push`]: #method.push
 /// [`push_str`]: #method.push_str
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index dc0905e2972..e0a3b8d52f4 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -998,7 +998,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// A method would interfere with methods of the same name on the contents
     /// of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, Ref};
@@ -1040,7 +1040,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// `RefMut::map(...)`.  A method would interfere with methods of the same
     /// name on the contents of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, RefMut};
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 8125097d7d1..b594c886b64 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -58,7 +58,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
 /// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -153,7 +153,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
 /// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -290,7 +290,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
 /// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -361,7 +361,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
 /// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -432,7 +432,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
 /// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 6f7adbe1e7a..4b866cab1ea 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -901,7 +901,7 @@ impl<T> ManuallyDrop<T> {
 
     /// Manually drops the contained value.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function runs the destructor of the contained value and thus the wrapped value
     /// now represents uninitialized data. It is up to the user of this method to ensure the
diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs
index 21410dcd412..112f424f7a8 100644
--- a/src/librustc_back/target/haiku_base.rs
+++ b/src/librustc_back/target/haiku_base.rs
@@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
         target_family: Some("unix".to_string()),
         relro_level: RelroLevel::Full,
         linker_is_gnu: true,
-        no_integrated_as: true,
         .. Default::default()
     }
 }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 195bd2acce0..cbc4ebe90fd 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -160,21 +160,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
         };
 
         let mut fn_warned = false;
-        let maybe_def = match expr.node {
-            hir::ExprCall(ref callee, _) => {
-                match callee.node {
-                    hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)),
-                    _ => None
-                }
-            },
-            hir::ExprMethodCall(..) => {
-                cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
-            },
-            _ => { None }
-        };
-        if let Some(def) = maybe_def {
-            let def_id = def.def_id();
-            fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+        if cx.tcx.sess.features.borrow().fn_must_use {
+            let maybe_def = match expr.node {
+                hir::ExprCall(ref callee, _) => {
+                    match callee.node {
+                        hir::ExprPath(ref qpath) => {
+                            Some(cx.tables.qpath_def(qpath, callee.hir_id))
+                        },
+                        _ => None
+                    }
+                },
+                hir::ExprMethodCall(..) => {
+                    cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
+                },
+                _ => None
+            };
+            if let Some(def) = maybe_def {
+                let def_id = def.def_id();
+                fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+            }
         }
 
         if !(ty_warned || fn_warned) {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 92b3180c5cb..7d6ad5286d1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -323,6 +323,10 @@ impl Item {
     pub fn is_union(&self) -> bool {
         self.type_() == ItemType::Union
     }
+    pub fn is_import(&self) -> bool {
+        self.type_() == ItemType::Import
+    }
+
     pub fn is_stripped(&self) -> bool {
         match self.inner { StrippedItem(..) => true, _ => false }
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 6593d6dfd6c..5457f69cb6d 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1764,6 +1764,37 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
+    // This call is to remove reexport duplicates in cases such as:
+    //
+    // ```
+    // pub mod foo {
+    //     pub mod bar {
+    //         pub trait Double { fn foo(); }
+    //     }
+    // }
+    //
+    // pub use foo::bar::*;
+    // pub use foo::*;
+    // ```
+    //
+    // `Double` will appear twice in the generated docs.
+    //
+    // FIXME: This code is quite ugly and could be improved. Small issue: DefId
+    // can be identical even if the elements are different (mostly in imports).
+    // So in case this is an import, we keep everything by adding a "unique id"
+    // (which is the position in the vector).
+    indices.dedup_by_key(|i| (items[*i].def_id,
+                              if items[*i].name.as_ref().is_some() {
+                                  Some(full_path(cx, &items[*i]).clone())
+                              } else {
+                                  None
+                              },
+                              items[*i].type_(),
+                              if items[*i].is_import() {
+                                  *i
+                              } else {
+                                  0
+                              }));
 
     debug!("{:?}", indices);
     let mut curty = None;
@@ -2925,7 +2956,13 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
 fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
                render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result {
     if render_mode == RenderMode::Normal {
-        write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
+        let id = derive_id(match i.inner_impl().trait_ {
+            Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
+            None => "impl".to_string(),
+        });
+        write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
+               id, i.inner_impl())?;
+        write!(w, "<a href='#{}' class='anchor'></a>", id)?;
         write!(w, "</span><span class='out-of-band'>")?;
         let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
         if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 26a64f6cd22..4a3286b421a 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -445,6 +445,10 @@ a {
 .small-section-header:hover > .anchor {
 	display: initial;
 }
+
+.in-band:hover > .anchor {
+	display: initial;
+}
 .anchor {
 	display: none;
 }
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css
index 08bf5a10fe9..c5f4272b932 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/styles/main.css
@@ -26,6 +26,7 @@ h1.fqn {
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
 	border-bottom-color: #DDDDDD;
 }
+
 .in-band {
 	background-color: white;
 }
@@ -83,6 +84,11 @@ pre {
 }
 
 :target { background: #FDFFD3; }
+
+:target > .in-band {
+	background: #FDFFD3;
+}
+
 .content .highlighted {
 	color: #000 !important;
 	background-color: #ccc;
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 0fff833e7d8..074ab3ebd8f 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -522,7 +522,7 @@ pub trait Read {
     /// `Read`er - the method only takes `&self` so that it can be used through
     /// trait objects.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This method is unsafe because a `Read`er could otherwise return a
     /// non-zeroing `Initializer` from another `Read` type without an `unsafe`
@@ -903,7 +903,7 @@ impl Initializer {
 
     /// Returns a new `Initializer` which will not zero out buffers.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This may only be called by `Read`ers which guarantee that they will not
     /// read from buffers passed to `Read` methods, and that the return value of
diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs
index 98642f86f4d..240e82069ff 100644
--- a/src/libstd/memchr.rs
+++ b/src/libstd/memchr.rs
@@ -20,7 +20,7 @@
 /// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
 /// (See benchmarks.)
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the first position of a byte in a byte string.
 ///
@@ -40,7 +40,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// Returns the index corresponding to the last occurrence of `needle` in
 /// `haystack`, or `None` if one is not found.
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the last position of a byte in a byte string.
 ///
diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs
index 259cda5bcb3..9fd8d6c9186 100644
--- a/src/libstd/sys/redox/ext/mod.rs
+++ b/src/libstd/sys/redox/ext/mod.rs
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index 67fe46cc9c7..98bc90dd4e1 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index ee103c803f5..6354e746af2 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -807,7 +807,7 @@ pub fn park_timeout_ms(ms: u32) {
 /// Platforms which do not support nanosecond precision for sleeping will have
 /// `dur` rounded up to the nearest granularity of time they can sleep for.
 ///
-/// # Example
+/// # Examples
 ///
 /// Waiting for the complete expiration of the timeout:
 ///
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 801343689b7..09574d5ba12 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -112,8 +112,8 @@ macro_rules! declare_features {
 // was set. This is most important for knowing when a particular feature became
 // stable (active).
 //
-// NB: The featureck.py script parses this information directly out of the source
-// so take care when modifying it.
+// NB: tools/tidy/src/features.rs parses this information directly out of the
+// source, so take care when modifying it.
 
 declare_features! (
     (active, asm, "1.0.0", Some(29722)),
@@ -372,6 +372,9 @@ declare_features! (
 
     // #[doc(cfg(...))]
     (active, doc_cfg, "1.21.0", Some(43781)),
+
+    // allow `#[must_use]` on functions (RFC 1940)
+    (active, fn_must_use, "1.21.0", Some(43302)),
 );
 
 declare_features! (
@@ -915,20 +918,27 @@ struct Context<'a> {
 }
 
 macro_rules! gate_feature_fn {
-    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
-        let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
+    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
+        let (cx, has_feature, span,
+             name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
         let has_feature: bool = has_feature(&$cx.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable() {
-            emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
+            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
+                .emit();
         }
     }}
 }
 
 macro_rules! gate_feature {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
-    }
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, GateStrength::Hard)
+    };
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, $level)
+    };
 }
 
 impl<'a> Context<'a> {
@@ -938,7 +948,7 @@ impl<'a> Context<'a> {
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
-                    gate_feature_fn!(self, has_feature, attr.span, name, desc);
+                    gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
                 }
                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
                 return;
@@ -1008,13 +1018,26 @@ pub enum GateIssue {
     Library(Option<u32>)
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum GateStrength {
+    /// A hard error. (Most feature gates should use this.)
+    Hard,
+    /// Only a warning. (Use this only as backwards-compatibility demands.)
+    Soft,
+}
+
 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
                         explain: &str) {
     feature_err(sess, feature, span, issue, explain).emit();
 }
 
 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
-                   explain: &str) -> DiagnosticBuilder<'a> {
+                       explain: &str) -> DiagnosticBuilder<'a> {
+    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
+}
+
+fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
+                           explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
     let diag = &sess.span_diagnostic;
 
     let issue = match issue {
@@ -1022,10 +1045,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
         GateIssue::Library(lib) => lib,
     };
 
-    let mut err = if let Some(n) = issue {
-        diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
+    let explanation = if let Some(n) = issue {
+        format!("{} (see issue #{})", explain, n)
     } else {
-        diag.struct_span_err(span, explain)
+        explain.to_owned()
+    };
+
+    let mut err = match level {
+        GateStrength::Hard => diag.struct_span_err(span, &explanation),
+        GateStrength::Soft => diag.struct_span_warn(span, &explanation),
     };
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -1035,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
                           feature));
     }
 
+    // If we're on stable and only emitting a "soft" warning, add a note to
+    // clarify that the feature isn't "on" (rather than being on but
+    // warning-worthy).
+    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
+        err.help("a nightly build of the compiler is required to enable this feature");
+    }
+
     err
+
 }
 
 const EXPLAIN_BOX_SYNTAX: &'static str =
@@ -1092,6 +1128,12 @@ macro_rules! gate_feature_post {
         if !span.allows_unstable() {
             gate_feature!(cx.context, $feature, span, $explain)
         }
+    }};
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
+        let (cx, span) = ($cx, $span);
+        if !span.allows_unstable() {
+            gate_feature!(cx.context, $feature, span, $explain, $level)
+        }
     }}
 }
 
@@ -1234,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                         function may change over time, for now \
                                         a top-level `fn main()` is required");
                 }
+                if attr::contains_name(&i.attrs[..], "must_use") {
+                    gate_feature_post!(&self, fn_must_use, i.span,
+                                       "`#[must_use]` on functions is experimental",
+                                       GateStrength::Soft);
+                }
             }
 
             ast::ItemKind::Struct(..) => {
@@ -1271,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                     and possibly buggy");
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
+            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
                                        i.span,
@@ -1284,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                        i.span,
                                        "specialization is unstable");
                 }
+
+                for impl_item in impl_items {
+                    if let ast::ImplItemKind::Method(..) = impl_item.node {
+                        if attr::contains_name(&impl_item.attrs[..], "must_use") {
+                            gate_feature_post!(&self, fn_must_use, impl_item.span,
+                                               "`#[must_use]` on methods is experimental",
+                                               GateStrength::Soft);
+                        }
+                    }
+                }
             }
 
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/compile-fail/feature-gate-fn_must_use.rs
new file mode 100644
index 00000000000..2dd6b904072
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-fn_must_use.rs
@@ -0,0 +1,31 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+struct MyStruct;
+
+impl MyStruct {
+    #[must_use]
+    fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
+}
+
+#[must_use]
+fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
+
+
+// Feature gates are tidy-required to have a specially named (or
+// comment-annotated) compile-fail test (which MUST fail), but for
+// backwards-compatibility reasons, we want `#[must_use]` on functions to be
+// compilable even if the `fn_must_use` feature is absent, thus necessitating
+// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
+// dilemma until a superior solution can be devised.
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 29a2b0609fc..204190d64ac 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -680,6 +680,7 @@ mod must_use {
     mod inner { #![must_use="1400"] }
 
     #[must_use = "1400"] fn f() { }
+    //~^ WARN `#[must_use]` on functions is experimental
 
     #[must_use = "1400"] struct S;
 
diff --git a/src/test/rustdoc/remove-duplicates.rs b/src/test/rustdoc/remove-duplicates.rs
new file mode 100644
index 00000000000..6c4f6d0700a
--- /dev/null
+++ b/src/test/rustdoc/remove-duplicates.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+mod foo {
+    pub use bar::*;
+    pub mod bar {
+        pub trait Foo {
+            fn foo();
+        }
+    }
+}
+
+// @count foo/index.html '//*[@class="trait"]' 1
+pub use foo::bar::*;
+pub use foo::*;
diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs
index 5aea5f2ca06..c549ded4db2 100644
--- a/src/test/ui/lint/fn_must_use.rs
+++ b/src/test/ui/lint/fn_must_use.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(fn_must_use)]
 #![warn(unused_must_use)]
 
 struct MyStruct {
diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr
index 20eb7452aea..242837793a0 100644
--- a/src/test/ui/lint/fn_must_use.stderr
+++ b/src/test/ui/lint/fn_must_use.stderr
@@ -1,18 +1,18 @@
 warning: unused return value of `need_to_use_this_value` which must be used: it's important
-  --> $DIR/fn_must_use.rs:30:5
+  --> $DIR/fn_must_use.rs:31:5
    |
-30 |     need_to_use_this_value();
+31 |     need_to_use_this_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/fn_must_use.rs:11:9
+  --> $DIR/fn_must_use.rs:12:9
    |
-11 | #![warn(unused_must_use)]
+12 | #![warn(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
 warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
-  --> $DIR/fn_must_use.rs:33:5
+  --> $DIR/fn_must_use.rs:34:5
    |
-33 |     m.need_to_use_this_method_value();
+34 |     m.need_to_use_this_method_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^