From 507381ed0367f27e8804a1da33f8565c96a260ce Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Sat, 13 Oct 2018 23:38:31 +0200
Subject: [PATCH 01/16] Fix ICE and report a human readable error

---
 src/librustc/ty/cast.rs                             |  2 ++
 src/librustc_mir/transform/qualify_min_const_fn.rs  | 13 ++++++++++---
 .../ui/consts/min_const_fn/bad_const_fn_body_ice.rs |  5 +++++
 .../min_const_fn/bad_const_fn_body_ice.stderr       | 10 ++++++++++
 4 files changed, 27 insertions(+), 3 deletions(-)
 create mode 100644 src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
 create mode 100644 src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr

diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs
index c0861abb774..ab82f28c8bf 100644
--- a/src/librustc/ty/cast.rs
+++ b/src/librustc/ty/cast.rs
@@ -58,6 +58,8 @@ pub enum CastKind {
 }
 
 impl<'tcx> CastTy<'tcx> {
+    /// Returns `Some` for integral/pointer casts.
+    /// casts like unsizing casts will return `None`
     pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
         match t.sty {
             ty::Bool => Some(CastTy::Int(IntTy::Bool)),
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index aa559c96ec6..edcae4648b7 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -148,7 +148,7 @@ fn check_rvalue(
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
             check_place(tcx, mir, place, span, PlaceMode::Read)
         }
-        Rvalue::Cast(_, operand, cast_ty) => {
+        Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
             use rustc::ty::cast::CastTy;
             let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast");
             let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
@@ -163,6 +163,10 @@ fn check_rvalue(
                 _ => check_operand(tcx, mir, operand, span),
             }
         }
+        Rvalue::Cast(_, _, _) => Err((
+            span,
+            "only int casts are allowed in const fn".into(),
+        )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
             check_operand(tcx, mir, lhs, span)?;
@@ -177,8 +181,11 @@ fn check_rvalue(
                 ))
             }
         }
-        // checked by regular const fn checks
-        Rvalue::NullaryOp(..) => Ok(()),
+        Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
+        Rvalue::NullaryOp(NullOp::Box, _) => Err((
+            span,
+            "heap allocations are not allowed in const fn".into(),
+        )),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(mir, tcx);
             if ty.is_integral() || ty.is_bool() {
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
new file mode 100644
index 00000000000..3e42cb8c1b0
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
@@ -0,0 +1,5 @@
+const fn foo(a: i32) -> Vec<i32> {
+    vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
new file mode 100644
index 00000000000..f6b704370b6
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
@@ -0,0 +1,10 @@
+error: heap allocations are not allowed in const fn
+  --> $DIR/bad_const_fn_body_ice.rs:2:5
+   |
+LL |     vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+   |     ^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+

From 34052047cf7cc30ccc8fbd947db56822d3d71423 Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 15 Oct 2018 19:58:21 +0200
Subject: [PATCH 02/16] Explain all casts in detail

---
 src/librustc_mir/transform/qualify_min_const_fn.rs | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index edcae4648b7..c9d48f5f6ad 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -163,9 +163,18 @@ fn check_rvalue(
                 _ => check_operand(tcx, mir, operand, span),
             }
         }
-        Rvalue::Cast(_, _, _) => Err((
+        Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
+        Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
             span,
-            "only int casts are allowed in const fn".into(),
+            "function pointer casts are not allowed in const fn".into(),
+        )),
+        Rvalue::Cast(CastKind::ClosureFnPointer, _, _) => Err((
+            span,
+            "closures are not allowed in const fn".into(),
+        )),
+        Rvalue::Cast(CastKind::Unsize, _, _) => Err((
+            span,
+            "unsizing casts are not allowed in const fn".into(),
         )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {

From 2456f330d508b223d8cfcada8652ad37b647996a Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 15 Oct 2018 20:10:16 +0200
Subject: [PATCH 03/16] Try to trigger some error cases

---
 .../ui/consts/min_const_fn/cast_errors.rs     | 14 ++++++++
 .../ui/consts/min_const_fn/cast_errors.stderr | 32 +++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 src/test/ui/consts/min_const_fn/cast_errors.rs
 create mode 100644 src/test/ui/consts/min_const_fn/cast_errors.stderr

diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs
new file mode 100644
index 00000000000..36827b1b6b0
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.rs
@@ -0,0 +1,14 @@
+fn main() {}
+
+const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+//~^ ERROR unsizing casts are not allowed in const fn
+const fn closure() -> fn() { || {} }
+//~^ ERROR function pointers in const fn are unstable
+const fn closure2() {
+    (|| {}) as fn();
+//~^ ERROR function pointers in const fn are unstable
+}
+const fn reify(f: fn()) -> unsafe fn() { f }
+//~^ ERROR function pointers in const fn are unstable
+const fn reify2() { main as unsafe fn(); }
+//~^ ERROR function pointers in const fn are unstable
\ No newline at end of file
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr
new file mode 100644
index 00000000000..ba980b7aacb
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr
@@ -0,0 +1,32 @@
+error: unsizing casts are not allowed in const fn
+  --> $DIR/cast_errors.rs:3:41
+   |
+LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+   |                                         ^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:5:23
+   |
+LL | const fn closure() -> fn() { || {} }
+   |                       ^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:8:5
+   |
+LL |     (|| {}) as fn();
+   |     ^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:11:28
+   |
+LL | const fn reify(f: fn()) -> unsafe fn() { f }
+   |                            ^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:13:21
+   |
+LL | const fn reify2() { main as unsafe fn(); }
+   |                     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+

From 007390c21cc5e5e8705d455d20fba1df13bd7362 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?=
 =?UTF-8?q?e=CC=B6r=20Scherer?= <github35764891676564198441@oli-obk.de>
Date: Mon, 15 Oct 2018 20:30:11 +0200
Subject: [PATCH 04/16] Add trailing newline to satisfy tidy

---
 src/test/ui/consts/min_const_fn/cast_errors.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs
index 36827b1b6b0..8648cd35387 100644
--- a/src/test/ui/consts/min_const_fn/cast_errors.rs
+++ b/src/test/ui/consts/min_const_fn/cast_errors.rs
@@ -11,4 +11,4 @@ const fn closure2() {
 const fn reify(f: fn()) -> unsafe fn() { f }
 //~^ ERROR function pointers in const fn are unstable
 const fn reify2() { main as unsafe fn(); }
-//~^ ERROR function pointers in const fn are unstable
\ No newline at end of file
+//~^ ERROR function pointers in const fn are unstable

From 38f3ad41c0bbf6ed7c389a070afb60a465b3afe3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?=
 =?UTF-8?q?e=CC=B6r=20Scherer?= <github35764891676564198441@oli-obk.de>
Date: Wed, 17 Oct 2018 09:04:10 +0200
Subject: [PATCH 05/16] Squash closure cast error into fn ptr cast error

---
 src/librustc_mir/transform/qualify_min_const_fn.rs | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index c9d48f5f6ad..52c557b83d5 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -164,14 +164,11 @@ fn check_rvalue(
             }
         }
         Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
+        Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
         Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
             span,
             "function pointer casts are not allowed in const fn".into(),
         )),
-        Rvalue::Cast(CastKind::ClosureFnPointer, _, _) => Err((
-            span,
-            "closures are not allowed in const fn".into(),
-        )),
         Rvalue::Cast(CastKind::Unsize, _, _) => Err((
             span,
             "unsizing casts are not allowed in const fn".into(),

From da40916bc20880785daec954ee20ee18464ecb7a Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Wed, 17 Oct 2018 11:13:44 +0200
Subject: [PATCH 06/16] resolve: improve common patterns

---
 src/librustc_resolve/build_reduced_graph.rs |  11 +-
 src/librustc_resolve/check_unused.rs        |   6 +-
 src/librustc_resolve/lib.rs                 |  63 ++++-----
 src/librustc_resolve/resolve_imports.rs     | 146 ++++++++++----------
 4 files changed, 105 insertions(+), 121 deletions(-)

diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 25a7ff9cd3f..e2f5829d14f 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -139,7 +139,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
 
         let prefix_iter = || parent_prefix.iter().cloned()
             .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
-        let prefix_start = prefix_iter().nth(0);
+        let prefix_start = prefix_iter().next();
         let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
             !ident.is_path_segment_keyword()
         });
@@ -1048,13 +1048,10 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
 
     fn visit_token(&mut self, t: Token) {
         if let Token::Interpolated(nt) = t {
-            match nt.0 {
-                token::NtExpr(ref expr) => {
-                    if let ast::ExprKind::Mac(..) = expr.node {
-                        self.visit_invoc(expr.id);
-                    }
+            if let token::NtExpr(ref expr) = nt.0 {
+                if let ast::ExprKind::Mac(..) = expr.node {
+                    self.visit_invoc(expr.id);
                 }
-                _ => {}
             }
         }
     }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index de9481579e2..6f3135b37cf 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -109,7 +109,7 @@ impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> {
                 self.item_span
             };
 
-            if items.len() == 0 {
+            if items.is_empty() {
                 self.unused_imports
                     .entry(self.base_id)
                     .or_default()
@@ -170,7 +170,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
 
     for (id, spans) in &visitor.unused_imports {
         let len = spans.len();
-        let mut spans = spans.values().map(|s| *s).collect::<Vec<Span>>();
+        let mut spans = spans.values().cloned().collect::<Vec<Span>>();
         spans.sort();
         let ms = MultiSpan::from_spans(spans.clone());
         let mut span_snippets = spans.iter()
@@ -183,7 +183,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
         span_snippets.sort();
         let msg = format!("unused import{}{}",
                           if len > 1 { "s" } else { "" },
-                          if span_snippets.len() > 0 {
+                          if !span_snippets.is_empty() {
                               format!(": {}", span_snippets.join(", "))
                           } else {
                               String::new()
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 86fe584dc3a..5f821cc71c9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1633,19 +1633,17 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
-            PathResult::NonModule(..) => match self.resolve_path(
-                None,
-                &path,
-                None,
-                true,
-                span,
-                CrateLint::No,
-            ) {
-                PathResult::Failed(span, msg, _) => {
+            PathResult::NonModule(..) =>
+                if let PathResult::Failed(span, msg, _) = self.resolve_path(
+                    None,
+                    &path,
+                    None,
+                    true,
+                    span,
+                    CrateLint::No,
+                ) {
                     error_callback(self, span, ResolutionError::FailedToResolve(&msg));
-                }
-                _ => {}
-            },
+                },
             PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
             PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
@@ -2351,7 +2349,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     span: prefix.span.to(use_tree.prefix.span),
                 };
 
-                if items.len() == 0 {
+                if items.is_empty() {
                     // Resolve prefix of an import with empty braces (issue #28388).
                     self.smart_resolve_path_with_crate_lint(
                         id,
@@ -2690,7 +2688,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
                 let map_j = self.binding_mode_map(&q);
                 for (&key, &binding_i) in &map_i {
-                    if map_j.len() == 0 {                   // Account for missing bindings when
+                    if map_j.is_empty() {                   // Account for missing bindings when
                         let binding_error = missing_vars    // map_j has none.
                             .entry(key.name)
                             .or_insert(BindingError {
@@ -2751,9 +2749,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         // This has to happen *after* we determine which pat_idents are variants
         self.check_consistent_bindings(&arm.pats);
 
-        match arm.guard {
-            Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
-            _ => {}
+        if let Some(ast::Guard::If(ref expr)) = arm.guard {
+            self.visit_expr(expr)
         }
         self.visit_expr(&arm.body);
 
@@ -2994,14 +2991,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             // Make the base error.
             let expected = source.descr_expected();
             let path_str = names_to_string(path);
-            let item_str = path[path.len() - 1];
+            let item_str = path.last().unwrap();
             let code = source.error_code(def.is_some());
             let (base_msg, fallback_label, base_span) = if let Some(def) = def {
                 (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
                  format!("not a {}", expected),
                  span)
             } else {
-                let item_span = path[path.len() - 1].span;
+                let item_span = path.last().unwrap().span;
                 let (mod_prefix, mod_str) = if path.len() == 1 {
                     (String::new(), "this scope".to_string())
                 } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() {
@@ -3368,7 +3365,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                             );
                         }
                         break;
-                    } else if snippet.trim().len() != 0  {
+                    } else if !snippet.trim().is_empty() {
                         debug!("tried to find type ascription `:` token, couldn't find it");
                         break;
                     }
@@ -3930,7 +3927,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             }
             _ => {}
         }
-        return def;
+        def
     }
 
     fn lookup_assoc_candidate<FilterFn>(&mut self,
@@ -4482,21 +4479,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             let extern_prelude_names = self.extern_prelude.clone();
             for &name in extern_prelude_names.iter() {
                 let ident = Ident::with_empty_ctxt(name);
-                match self.crate_loader.maybe_process_path_extern(name, ident.span) {
-                    Some(crate_id) => {
-                        let crate_root = self.get_module(DefId {
-                            krate: crate_id,
-                            index: CRATE_DEF_INDEX,
-                        });
-                        self.populate_module_if_necessary(&crate_root);
+                if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name,
+                                                                                    ident.span)
+                {
+                    let crate_root = self.get_module(DefId {
+                        krate: crate_id,
+                        index: CRATE_DEF_INDEX,
+                    });
+                    self.populate_module_if_necessary(&crate_root);
 
-                        suggestions.extend(
-                            self.lookup_import_candidates_from_module(
-                                lookup_name, namespace, crate_root, ident, &filter_fn
-                            )
-                        );
-                    }
-                    None => {}
+                    suggestions.extend(self.lookup_import_candidates_from_module(
+                        lookup_name, namespace, crate_root, ident, &filter_fn));
                 }
             }
         }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 48f312ce9f2..d5d772e1359 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -672,7 +672,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 };
 
                 let has_explicit_self =
-                    import.module_path.len() > 0 &&
+                    !import.module_path.is_empty() &&
                     import.module_path[0].name == keywords::SelfValue.name();
 
                 self.per_ns(|_, ns| {
@@ -703,9 +703,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 if let SingleImport { source, ref result, .. } = import.subclass {
                     if source.name == "self" {
                         // Silence `unresolved import` error if E0429 is already emitted
-                        match result.value_ns.get() {
-                            Err(Determined) => continue,
-                            _ => {},
+                        if let Err(Determined) = result.value_ns.get() {
+                            continue;
                         }
                     }
                 }
@@ -822,20 +821,19 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>,
                                      span: Option<MultiSpan>) {
         let max_span_label_msg_count = 10;  // upper limit on number of span_label message.
-        let (span,msg) = match error_vec.is_empty() {
-            true => (span.unwrap(), "unresolved import".to_string()),
-            false => {
-                let span = MultiSpan::from_spans(error_vec.clone().into_iter()
-                                    .map(|elem: (Span, String, String)| { elem.0 }
-                                    ).collect());
-                let path_vec: Vec<String> = error_vec.clone().into_iter()
-                                .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) }
-                                ).collect();
-                let path = path_vec.join(", ");
-                let msg = format!("unresolved import{} {}",
-                                if path_vec.len() > 1 { "s" } else { "" },  path);
-                (span, msg)
-            }
+        let (span, msg) = if error_vec.is_empty() {
+            (span.unwrap(), "unresolved import".to_string())
+        } else {
+            let span = MultiSpan::from_spans(error_vec.clone().into_iter()
+                .map(|elem: (Span, String, String)| { elem.0 })
+                .collect());
+            let path_vec: Vec<String> = error_vec.clone().into_iter()
+                .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) })
+                .collect();
+            let path = path_vec.join(", ");
+            let msg = format!("unresolved import{} {}",
+                if path_vec.len() > 1 { "s" } else { "" }, path);
+            (span, msg)
         };
         let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
         for span_error in error_vec.into_iter().take(max_span_label_msg_count) {
@@ -1026,9 +1024,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
         if all_ns_err {
             let mut all_ns_failed = true;
             self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
-                match this.resolve_ident_in_module(module, ident, ns, record_used, span) {
-                    Ok(_) => all_ns_failed = false,
-                    _ => {}
+                if this.resolve_ident_in_module(module, ident, ns, record_used, span).is_ok() {
+                    all_ns_failed = false;
                 }
             });
 
@@ -1247,65 +1244,62 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 }
             }
 
-            match binding.kind {
-                NameBindingKind::Import { binding: orig_binding, directive, .. } => {
-                    if ns == TypeNS && orig_binding.is_variant() &&
-                        !orig_binding.vis.is_at_least(binding.vis, &*self) {
-                            let msg = match directive.subclass {
-                                ImportDirectiveSubclass::SingleImport { .. } => {
-                                    format!("variant `{}` is private and cannot be re-exported",
-                                            ident)
-                                },
-                                ImportDirectiveSubclass::GlobImport { .. } => {
-                                    let msg = "enum is private and its variants \
-                                               cannot be re-exported".to_owned();
-                                    let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
-                                                    Some(binding.span),
-                                                    msg.clone());
-                                    let fresh = self.session.one_time_diagnostics
-                                        .borrow_mut().insert(error_id);
-                                    if !fresh {
-                                        continue;
-                                    }
-                                    msg
-                                },
-                                ref s @ _ => bug!("unexpected import subclass {:?}", s)
-                            };
-                            let mut err = self.session.struct_span_err(binding.span, &msg);
+            if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
+                if ns == TypeNS && orig_binding.is_variant() &&
+                    !orig_binding.vis.is_at_least(binding.vis, &*self) {
+                        let msg = match directive.subclass {
+                            ImportDirectiveSubclass::SingleImport { .. } => {
+                                format!("variant `{}` is private and cannot be re-exported",
+                                        ident)
+                            },
+                            ImportDirectiveSubclass::GlobImport { .. } => {
+                                let msg = "enum is private and its variants \
+                                           cannot be re-exported".to_owned();
+                                let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
+                                                Some(binding.span),
+                                                msg.clone());
+                                let fresh = self.session.one_time_diagnostics
+                                    .borrow_mut().insert(error_id);
+                                if !fresh {
+                                    continue;
+                                }
+                                msg
+                            },
+                            ref s @ _ => bug!("unexpected import subclass {:?}", s)
+                        };
+                        let mut err = self.session.struct_span_err(binding.span, &msg);
 
-                            let imported_module = match directive.imported_module.get() {
-                                Some(ModuleOrUniformRoot::Module(module)) => module,
-                                _ => bug!("module should exist"),
-                            };
-                            let resolutions = imported_module.parent.expect("parent should exist")
-                                .resolutions.borrow();
-                            let enum_path_segment_index = directive.module_path.len() - 1;
-                            let enum_ident = directive.module_path[enum_path_segment_index];
+                        let imported_module = match directive.imported_module.get() {
+                            Some(ModuleOrUniformRoot::Module(module)) => module,
+                            _ => bug!("module should exist"),
+                        };
+                        let resolutions = imported_module.parent.expect("parent should exist")
+                            .resolutions.borrow();
+                        let enum_path_segment_index = directive.module_path.len() - 1;
+                        let enum_ident = directive.module_path[enum_path_segment_index];
 
-                            let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
-                                .expect("resolution should exist");
-                            let enum_span = enum_resolution.borrow()
-                                .binding.expect("binding should exist")
-                                .span;
-                            let enum_def_span = self.session.source_map().def_span(enum_span);
-                            let enum_def_snippet = self.session.source_map()
-                                .span_to_snippet(enum_def_span).expect("snippet should exist");
-                            // potentially need to strip extant `crate`/`pub(path)` for suggestion
-                            let after_vis_index = enum_def_snippet.find("enum")
-                                .expect("`enum` keyword should exist in snippet");
-                            let suggestion = format!("pub {}",
-                                                     &enum_def_snippet[after_vis_index..]);
+                        let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
+                            .expect("resolution should exist");
+                        let enum_span = enum_resolution.borrow()
+                            .binding.expect("binding should exist")
+                            .span;
+                        let enum_def_span = self.session.source_map().def_span(enum_span);
+                        let enum_def_snippet = self.session.source_map()
+                            .span_to_snippet(enum_def_span).expect("snippet should exist");
+                        // potentially need to strip extant `crate`/`pub(path)` for suggestion
+                        let after_vis_index = enum_def_snippet.find("enum")
+                            .expect("`enum` keyword should exist in snippet");
+                        let suggestion = format!("pub {}",
+                                                 &enum_def_snippet[after_vis_index..]);
 
-                            self.session
-                                .diag_span_suggestion_once(&mut err,
-                                                           DiagnosticMessageId::ErrorId(0),
-                                                           enum_def_span,
-                                                           "consider making the enum public",
-                                                           suggestion);
-                            err.emit();
-                    }
+                        self.session
+                            .diag_span_suggestion_once(&mut err,
+                                                       DiagnosticMessageId::ErrorId(0),
+                                                       enum_def_span,
+                                                       "consider making the enum public",
+                                                       suggestion);
+                        err.emit();
                 }
-                _ => {}
             }
         }
 

From 89c20b78d68345040d68f0b475276687d10fdc92 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Wed, 17 Oct 2018 11:36:19 +0200
Subject: [PATCH 07/16] resolve: improve/remove allocations

---
 src/librustc_resolve/lib.rs    | 20 +++++---------------
 src/librustc_resolve/macros.rs |  7 +++----
 2 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5f821cc71c9..131b69429c6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3021,10 +3021,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
 
             // Emit help message for fake-self from other languages like `this`(javascript)
-            let fake_self: Vec<Ident> = ["this", "my"].iter().map(
-                |s| Ident::from_str(*s)
-            ).collect();
-            if fake_self.contains(&item_str)
+            if ["this", "my"].contains(&&*item_str.as_str())
                 && this.self_value_is_available(path[0].span, span) {
                 err.span_suggestion_with_applicability(
                     span,
@@ -4377,10 +4374,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         where FilterFn: Fn(Def) -> bool
     {
         let mut candidates = Vec::new();
-        let mut worklist = Vec::new();
         let mut seen_modules = FxHashSet();
         let not_local_module = crate_name != keywords::Crate.ident();
-        worklist.push((start_module, Vec::<ast::PathSegment>::new(), not_local_module));
+        let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
 
         while let Some((in_module,
                         path_segments,
@@ -4467,13 +4463,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                                           -> Vec<ImportSuggestion>
         where FilterFn: Fn(Def) -> bool
     {
-        let mut suggestions = vec![];
-
-        suggestions.extend(
-            self.lookup_import_candidates_from_module(
-                lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn
-            )
-        );
+        let mut suggestions = self.lookup_import_candidates_from_module(
+            lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
 
         if self.session.rust_2018() {
             let extern_prelude_names = self.extern_prelude.clone();
@@ -4502,9 +4493,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                    -> Option<(Module<'a>, ImportSuggestion)>
     {
         let mut result = None;
-        let mut worklist = Vec::new();
         let mut seen_modules = FxHashSet();
-        worklist.push((self.graph_root, Vec::new()));
+        let mut worklist = vec![(self.graph_root, Vec::new())];
 
         while let Some((in_module, path_segments)) = worklist.pop() {
             // abort if the module is already found
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 6c57e6c88ab..28284a45bcd 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -203,9 +203,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
         self.current_module = invocation.module.get();
         self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         self.current_module.unresolved_invocations.borrow_mut().extend(derives);
-        for &derive in derives {
-            self.invocations.insert(derive, invocation);
-        }
+        self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
         let mut visitor = BuildReducedGraphVisitor {
             resolver: self,
             current_legacy_scope: invocation.parent_legacy_scope.get(),
@@ -277,11 +275,12 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
                     if traits.is_empty() {
                         attrs.remove(i);
                     } else {
-                        let mut tokens = Vec::new();
+                        let mut tokens = Vec::with_capacity(traits.len() - 1);
                         for (j, path) in traits.iter().enumerate() {
                             if j > 0 {
                                 tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into());
                             }
+                            tokens.reserve((path.segments.len() * 2).saturating_sub(1));
                             for (k, segment) in path.segments.iter().enumerate() {
                                 if k > 0 {
                                     tokens.push(TokenTree::Token(path.span, Token::ModSep).into());

From 0a858dc859f828af2c578bcf23418dd14c767f3c Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 17 Oct 2018 23:51:01 +0100
Subject: [PATCH 08/16] Don't warn about parentheses on `match (return)`

---
 src/librustc_lint/unused.rs                       | 13 ++++++++-----
 src/test/ui/lint/no-unused-parens-return-block.rs |  6 ++++++
 2 files changed, 14 insertions(+), 5 deletions(-)
 create mode 100644 src/test/ui/lint/no-unused-parens-return-block.rs

diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 76717548521..4cf2072e792 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -276,10 +276,13 @@ impl UnusedParens {
                                 cx: &EarlyContext,
                                 value: &ast::Expr,
                                 msg: &str,
-                                struct_lit_needs_parens: bool) {
+                                followed_by_block: bool) {
         if let ast::ExprKind::Paren(ref inner) = value.node {
-            let necessary = struct_lit_needs_parens &&
-                            parser::contains_exterior_struct_lit(&inner);
+            let necessary = followed_by_block && if let ast::ExprKind::Ret(_) = inner.node {
+                true
+            } else {
+                parser::contains_exterior_struct_lit(&inner)
+            };
             if !necessary {
                 let pattern = pprust::expr_to_string(value);
                 Self::remove_outer_parens(cx, value.span, &pattern, msg);
@@ -343,7 +346,7 @@ impl LintPass for UnusedParens {
 impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
         use syntax::ast::ExprKind::*;
-        let (value, msg, struct_lit_needs_parens) = match e.node {
+        let (value, msg, followed_by_block) = match e.node {
             If(ref cond, ..) => (cond, "`if` condition", true),
             While(ref cond, ..) => (cond, "`while` condition", true),
             IfLet(_, ref cond, ..) => (cond, "`if let` head expression", true),
@@ -380,7 +383,7 @@ impl EarlyLintPass for UnusedParens {
                 return;
             }
         };
-        self.check_unused_parens_expr(cx, &value, msg, struct_lit_needs_parens);
+        self.check_unused_parens_expr(cx, &value, msg, followed_by_block);
     }
 
     fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) {
diff --git a/src/test/ui/lint/no-unused-parens-return-block.rs b/src/test/ui/lint/no-unused-parens-return-block.rs
new file mode 100644
index 00000000000..fc8dbb743e1
--- /dev/null
+++ b/src/test/ui/lint/no-unused-parens-return-block.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+fn main() {
+    match (return) {} // ok
+    if (return) {} // ok
+}

From 0e6c3f29be98176c91aa77eb71c04cca18c51115 Mon Sep 17 00:00:00 2001
From: Raph Levien <raph.levien@gmail.com>
Date: Wed, 17 Oct 2018 18:15:00 -0700
Subject: [PATCH 09/16] Add a `copysign` function to f32 and f64

This patch adds a `copysign` function to the float primitive types.
It is an exceptionally useful function for writing efficient numeric
code, as it often avoids branches, is auto-vectorizable, and there
are efficient intrinsics for most platforms.

I think this might work as-is, as the relevant `copysign` intrinsic
is already used internally for the implementation of `signum`. It's
possible that an implementation might be needed in japaric/libm for
portability across all platforms, in which case I'll do that also.

Part of the work towards #55107
---
 src/libstd/f32.rs | 28 ++++++++++++++++++++++++++++
 src/libstd/f64.rs | 27 +++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 8e8340b3ed9..4ae8d2dcf16 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -198,6 +198,34 @@ impl f32 {
         }
     }
 
+    /// Returns a number composed of the magnitude of one number and the sign of
+    /// another.
+    ///
+    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y`
+    /// is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(copysign)]
+    /// use std::f32;
+    ///
+    /// let f = 3.5_f32;
+    ///
+    /// assert_eq!(f.copysign(0.42), 3.5_f32);
+    /// assert_eq!(f.copysign(-0.42), -3.5_f32);
+    /// assert_eq!((-f).copysign(0.42), 3.5_f32);
+    /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
+    ///
+    /// assert!(f32::NAN.copysign(1.0).is_nan());
+    /// ```
+    #[inline]
+    #[unstable(feature="copysign", issue="0")]
+    pub fn copysign(self, y: f32) -> f32 {
+        unsafe { intrinsics::copysignf32(self, y) }
+    }
+
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error, yielding a more accurate result than an unfused multiply-add.
     ///
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 6880294afca..3b805d6fa42 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -176,6 +176,33 @@ impl f64 {
         }
     }
 
+    /// Returns a number composed of the magnitude of one number and the sign of
+    /// another, or `NAN` if the number is `NAN`.
+    ///
+    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// equal to `-y`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(copysign)]
+    /// use std::f64;
+    ///
+    /// let f = 3.5_f64;
+    ///
+    /// assert_eq!(f.copysign(0.42), 3.5_f64);
+    /// assert_eq!(f.copysign(-0.42), -3.5_f64);
+    /// assert_eq!((-f).copysign(0.42), 3.5_f64);
+    /// assert_eq!((-f).copysign(-0.42), -3.5_f64);
+    ///
+    /// assert!(f64::NAN.copysign(1.0).is_nan());
+    /// ```
+    #[inline]
+    #[unstable(feature="copysign", issue="0")]
+    pub fn copysign(self, y: f64) -> f64 {
+        unsafe { intrinsics::copysignf64(self, y) }
+    }
+
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error, yielding a more accurate result than an unfused multiply-add.
     ///

From 9a2e7026dcbd84641b05334b5b4b0a4d647944f4 Mon Sep 17 00:00:00 2001
From: Raph Levien <raph.levien@gmail.com>
Date: Wed, 17 Oct 2018 21:09:55 -0700
Subject: [PATCH 10/16] Fix inconsistent documentation

I improved the f32 version and made a copy-paste error for f64.
---
 src/libstd/f32.rs | 2 +-
 src/libstd/f64.rs | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 4ae8d2dcf16..369745d8189 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -221,7 +221,7 @@ impl f32 {
     /// assert!(f32::NAN.copysign(1.0).is_nan());
     /// ```
     #[inline]
-    #[unstable(feature="copysign", issue="0")]
+    #[unstable(feature="copysign", issue="55169")]
     pub fn copysign(self, y: f32) -> f32 {
         unsafe { intrinsics::copysignf32(self, y) }
     }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 3b805d6fa42..df23d62ecfd 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -177,10 +177,11 @@ impl f64 {
     }
 
     /// Returns a number composed of the magnitude of one number and the sign of
-    /// another, or `NAN` if the number is `NAN`.
+    /// another.
     ///
     /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
-    /// equal to `-y`.
+    /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y`
+    /// is returned.
     ///
     /// # Examples
     ///
@@ -198,7 +199,7 @@ impl f64 {
     /// assert!(f64::NAN.copysign(1.0).is_nan());
     /// ```
     #[inline]
-    #[unstable(feature="copysign", issue="0")]
+    #[unstable(feature="copysign", issue="55169")]
     pub fn copysign(self, y: f64) -> f64 {
         unsafe { intrinsics::copysignf64(self, y) }
     }

From 40bba70823466eb1458a4fd99a4f644411b4eae4 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Thu, 18 Oct 2018 10:35:01 +0100
Subject: [PATCH 11/16] Make warnings into errors

---
 src/test/ui/lint/no-unused-parens-return-block.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/test/ui/lint/no-unused-parens-return-block.rs b/src/test/ui/lint/no-unused-parens-return-block.rs
index fc8dbb743e1..37dc519a204 100644
--- a/src/test/ui/lint/no-unused-parens-return-block.rs
+++ b/src/test/ui/lint/no-unused-parens-return-block.rs
@@ -1,5 +1,8 @@
 // run-pass
 
+#![deny(unused_parens)]
+#![allow(unreachable_code)]
+
 fn main() {
     match (return) {} // ok
     if (return) {} // ok

From 518a5a4898799e4b6732ac217f85def83fc462aa Mon Sep 17 00:00:00 2001
From: Aaron Power <theaaronepower@gmail.com>
Date: Mon, 17 Sep 2018 17:44:04 +0100
Subject: [PATCH 12/16] Updated RELEASES.md for 1.30.0

---
 RELEASES.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/RELEASES.md b/RELEASES.md
index 9bc750ddef5..b40897a7509 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,124 @@
+Version 1.30.0 (2018-10-25)
+==========================
+
+Language
+--------
+- [Procedural macros are now available.][52081] These kinds of macros allow for
+  more powerful code generation, there is a [new chapter available][proc-macros]
+  in Rust Programming Language book that goes further in depth.
+- [You can now use keywords as identifiers using the raw identifiers
+  syntax (`r#`).][53236] e.g. `let r#bool = true;`
+- [Using anonymous parameters in traits is now deprecated with a warning and
+  will be a hard error in the 2018 edition.][53272]
+- [You can now use `crate` in paths.][54404] This allows you to refer to the
+  crate root in the path. e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`.
+- [Using a external crate now no longer requires being prefixed with `::`.][54404]
+  e.g. previously using a external crate in a module without a use statement
+  required `let json = ::serde_json::from_str(foo);` can now be written
+  as `let json = serde_json::from_str(foo);`.
+- [You can now apply the `#[used]` attribute to static items to prevent the
+  compiler from optimising them away even if they appear to be unused.][51363]
+  e.g. `#[used] static FOO: u32 = 1;`
+- [You can now import and reexport macros from other crates with the `use`
+  syntax.][50911] Macros exported with `#[macro_export]` are now placed into
+  the root module of the crate. If your macro relies on calling other local
+  macros it is recommended to export with the
+  `#[macro_export(local_inner_macros)]` attribute so that users won't have to
+  import those macros.
+- [`mod.rs` files are now optional.][54146] Previously if you had a `foo` module
+  with a `bar` submodule, you would have `src/foo/mod.rs` and `src/foo/bar.rs`.
+  Now you can have `src/foo.rs` and `src/foo/bar.rs` to achieve the same effect.
+- [You can now catch visibility keywords (e.g. `pub`, `pub(crate)`) in macros
+  using the `vis` specifier.][53370]
+- [Non-macro attributes now allow all forms of literals not just
+  strings.][53044] e.g. Previously you would write `#[attr("true")]` you can now
+  write `#[attr(true)]`.
+- [You can now specify a function to handle a panic in the Rust runtime with the
+  `#[panic_handler]` attribute.][51366]
+
+Compiler
+--------
+- [Added the `riscv32imc-unknown-none-elf` target.][53822]
+- [Added the `aarch64-unknown-netbsd` target][53165]
+
+Libraries
+---------
+- [`ManuallyDrop` now allows the inner type to be unsized.][53033]
+
+Stabilized APIs
+---------------
+- [`Ipv4Addr::BROADCAST`]
+- [`Ipv4Addr::LOCALHOST`]
+- [`Ipv4Addr::UNSPECIFIED`]
+- [`Ipv6Addr::LOCALHOST`]
+- [`Ipv6Addr::UNSPECIFIED`]
+- [`Iterator::find_map`]
+
+  The following methods are a replacement methods for `trim_left`, `trim_right`,
+  `trim_left_matches`, and `trim_right_matches`. Which will be deprecated
+  in 1.33.0.
+- [`str::trim_end_matches`]
+- [`str::trim_end`]
+- [`str::trim_start_matches`]
+- [`str::trim_start`]
+
+Cargo
+----
+- [`cargo run` doesn't require specifying a package in workspaces.][cargo/5877]
+- [`cargo doc` now supports `--message-format=json`.][cargo/5878] This is
+  equivalent to calling `rustdoc --error-format=json`.
+- [You can specify which edition to create a project in cargo
+  with `cargo new --edition`.][cargo/5984] Currently only `2015` is a
+  valid option.
+- [Cargo will now provide a progress bar for builds.][cargo/5995]
+
+Misc
+----
+- [`rustdoc` allows you to specify what edition to treat your code as with the
+  `--edition` option.][54057]
+- [`rustdoc` now has the `--color` (Specify whether to output color) and
+  `--error-format` (Specify error format e.g. `json`) options.][53003]
+- [We now distribute a `rust-gdbgui` script that invokes `gdbgui` with Rust
+  debug symbols.][53774]
+- [Attributes from Rust tools such as `rustfmt` or `clippy` are now
+  available.][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item.
+
+[50911]: https://github.com/rust-lang/rust/pull/50911/
+[51363]: https://github.com/rust-lang/rust/pull/51363/
+[51366]: https://github.com/rust-lang/rust/pull/51366/
+[52081]: https://github.com/rust-lang/rust/pull/52081/
+[53003]: https://github.com/rust-lang/rust/pull/53003/
+[53033]: https://github.com/rust-lang/rust/pull/53033/
+[53044]: https://github.com/rust-lang/rust/pull/53044/
+[53165]: https://github.com/rust-lang/rust/pull/53165/
+[53213]: https://github.com/rust-lang/rust/pull/53213/
+[53236]: https://github.com/rust-lang/rust/pull/53236/
+[53272]: https://github.com/rust-lang/rust/pull/53272/
+[53370]: https://github.com/rust-lang/rust/pull/53370/
+[53459]: https://github.com/rust-lang/rust/pull/53459/
+[53774]: https://github.com/rust-lang/rust/pull/53774/
+[53822]: https://github.com/rust-lang/rust/pull/53822/
+[54057]: https://github.com/rust-lang/rust/pull/54057/
+[54146]: https://github.com/rust-lang/rust/pull/54146/
+[54404]: https://github.com/rust-lang/rust/pull/54404/
+[cargo/5877]: https://github.com/rust-lang/cargo/pull/5877/
+[cargo/5878]: https://github.com/rust-lang/cargo/pull/5878/
+[cargo/5984]: https://github.com/rust-lang/cargo/pull/5984/
+[cargo/5995]: https://github.com/rust-lang/cargo/pull/5995/
+[proc-macros]: https://doc.rust-lang.org/book/2018-edition/ch19-06-macros.html
+
+[`Ipv4Addr::BROADCAST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.BROADCAST
+[`Ipv4Addr::LOCALHOST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.LOCALHOST
+[`Ipv4Addr::UNSPECIFIED`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.UNSPECIFIED
+[`Ipv6Addr::LOCALHOST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#associatedconstant.LOCALHOST
+[`Ipv6Addr::UNSPECIFIED`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#associatedconstant.UNSPECIFIED
+[`Iterator::find_map`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find_map
+[`str::trim_end_matches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_end_matches
+[`str::trim_end`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_end
+[`str::trim_start_matches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_start_matches
+[`str::trim_start`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_start
+
+
 Version 1.29.2 (2018-10-11)
 ===========================
 
@@ -6,6 +127,7 @@ Version 1.29.2 (2018-10-11)
 
 [54639]: https://github.com/rust-lang/rust/pull/54639
 
+
 Version 1.29.1 (2018-09-25)
 ===========================
 
@@ -19,6 +141,7 @@ Security Notes
   Thank you to Scott McMurray for responsibily disclosing this vulnerability to
   us.
 
+
 Version 1.29.0 (2018-09-13)
 ==========================
 
@@ -73,7 +196,10 @@ Compatibility Notes
   Consider using the `home_dir` function from
   https://crates.io/crates/dirs instead.
 - [`rustc` will no longer silently ignore invalid data in target spec.][52330]
+- [`cfg` attributes and `--cfg` command line flags are now more
+  strictly validated.][53893]
 
+[53893]: https://github.com/rust-lang/rust/pull/53893/
 [52861]: https://github.com/rust-lang/rust/pull/52861/
 [52656]: https://github.com/rust-lang/rust/pull/52656/
 [52239]: https://github.com/rust-lang/rust/pull/52239/

From f08db6bf1ee44dd1bc8c4d3ddcea1425fcd8d118 Mon Sep 17 00:00:00 2001
From: Raph Levien <raph.levien@gmail.com>
Date: Thu, 18 Oct 2018 08:35:09 -0700
Subject: [PATCH 13/16] Add must_use on copysign

Added a #[must_use] annotation on copysign, per review feedback.
---
 src/libstd/f32.rs | 1 +
 src/libstd/f64.rs | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 369745d8189..c3f225d1eb0 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -221,6 +221,7 @@ impl f32 {
     /// assert!(f32::NAN.copysign(1.0).is_nan());
     /// ```
     #[inline]
+    #[must_use]
     #[unstable(feature="copysign", issue="55169")]
     pub fn copysign(self, y: f32) -> f32 {
         unsafe { intrinsics::copysignf32(self, y) }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index df23d62ecfd..da062dda77a 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -199,6 +199,7 @@ impl f64 {
     /// assert!(f64::NAN.copysign(1.0).is_nan());
     /// ```
     #[inline]
+    #[must_use]
     #[unstable(feature="copysign", issue="55169")]
     pub fn copysign(self, y: f64) -> f64 {
         unsafe { intrinsics::copysignf64(self, y) }

From b08ca2958e1b92c67c3ac0e76455f51742b95d23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 18 Oct 2018 10:22:34 +0300
Subject: [PATCH 14/16] Stabilize slice::chunks_exact() and
 slice::chunks_exact_mut()

Fixes #47115
---
 src/liballoc/lib.rs       |  1 -
 src/liballoc/slice.rs     |  2 +-
 src/liballoc/tests/lib.rs |  1 -
 src/libcore/slice/mod.rs  | 38 +++++++++++++++++---------------------
 src/libcore/tests/lib.rs  |  1 -
 5 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 0cad471d9a1..540a17774e5 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -115,7 +115,6 @@
 #![feature(unsize)]
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
-#![feature(chunks_exact)]
 #![feature(rustc_const_unstable)]
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 2628757b503..8ffc043d816 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -123,7 +123,7 @@ pub use core::slice::{from_raw_parts, from_raw_parts_mut};
 pub use core::slice::{from_ref, from_mut};
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 pub use core::slice::{ChunksExact, ChunksExactMut};
 #[unstable(feature = "rchunks", issue = "55177")]
 pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut};
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 62c84c9e086..5a21976d75d 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -19,7 +19,6 @@
 #![feature(str_escape)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(chunks_exact)]
 #![feature(rchunks)]
 #![feature(repeat_generic_slice)]
 
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 62f60034352..628d5542ac0 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -713,8 +713,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(chunks_exact)]
-    ///
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
     /// let mut iter = slice.chunks_exact(2);
     /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
@@ -725,7 +723,7 @@ impl<T> [T] {
     ///
     /// [`chunks`]: #method.chunks
     /// [`rchunks_exact`]: #method.rchunks_exact
-    #[unstable(feature = "chunks_exact", issue = "47115")]
+    #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<T> {
         assert!(chunk_size != 0);
@@ -756,8 +754,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(chunks_exact)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -772,7 +768,7 @@ impl<T> [T] {
     ///
     /// [`chunks_mut`]: #method.chunks_mut
     /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut
-    #[unstable(feature = "chunks_exact", issue = "47115")]
+    #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<T> {
         assert!(chunk_size != 0);
@@ -4022,25 +4018,25 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
 /// [`remainder`]: ../../std/slice/struct.ChunksExact.html#method.remainder
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 pub struct ChunksExact<'a, T:'a> {
     v: &'a [T],
     rem: &'a [T],
     chunk_size: usize
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
 impl<'a, T> ChunksExact<'a, T> {
     /// Return the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[stable(feature = "chunks_exact", since = "1.31.0")]
     pub fn remainder(&self) -> &'a [T] {
         self.rem
     }
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> Clone for ChunksExact<'_, T> {
     fn clone(&self) -> Self {
         ChunksExact {
@@ -4051,7 +4047,7 @@ impl<T> Clone for ChunksExact<'_, T> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<'a, T> Iterator for ChunksExact<'a, T> {
     type Item = &'a [T];
 
@@ -4096,7 +4092,7 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -4110,7 +4106,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> ExactSizeIterator for ChunksExact<'_, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4120,11 +4116,11 @@ impl<T> ExactSizeIterator for ChunksExact<'_, T> {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<T> TrustedLen for ChunksExact<'_, T> {}
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> FusedIterator for ChunksExact<'_, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
         let start = i * self.chunk_size;
@@ -4146,24 +4142,24 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
 /// [`into_remainder`]: ../../std/slice/struct.ChunksExactMut.html#method.into_remainder
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 pub struct ChunksExactMut<'a, T:'a> {
     v: &'a mut [T],
     rem: &'a mut [T],
     chunk_size: usize
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
 impl<'a, T> ChunksExactMut<'a, T> {
     /// Return the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[stable(feature = "chunks_exact", since = "1.31.0")]
     pub fn into_remainder(self) -> &'a mut [T] {
         self.rem
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<'a, T> Iterator for ChunksExactMut<'a, T> {
     type Item = &'a mut [T];
 
@@ -4210,7 +4206,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -4226,7 +4222,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> ExactSizeIterator for ChunksExactMut<'_, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4236,11 +4232,11 @@ impl<T> ExactSizeIterator for ChunksExactMut<'_, T> {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<T> TrustedLen for ChunksExactMut<'_, T> {}
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> FusedIterator for ChunksExactMut<'_, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
         let start = i * self.chunk_size;
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index e889d484353..affcdbea9d3 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -34,7 +34,6 @@
 #![feature(trusted_len)]
 #![feature(try_from)]
 #![feature(try_trait)]
-#![feature(chunks_exact)]
 #![feature(rchunks)]
 #![feature(align_offset)]
 #![feature(reverse_bits)]

From 52cc6fde4b73a3013ce2185052f9492ae3728367 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 18 Oct 2018 18:48:02 +0300
Subject: [PATCH 15/16] Stabilize slice::rchunks(), rchunks_mut(),
 rchunks_exact(), rchunk_exact_mut()

Fixes #55177
---
 src/liballoc/lib.rs       |  1 -
 src/liballoc/slice.rs     |  2 +-
 src/liballoc/tests/lib.rs |  1 -
 src/libcore/slice/mod.rs  | 72 +++++++++++++++++----------------------
 src/libcore/tests/lib.rs  |  1 -
 5 files changed, 33 insertions(+), 44 deletions(-)

diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 540a17774e5..84ca7c4fec9 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -119,7 +119,6 @@
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit)]
-#![feature(rchunks)]
 
 // Allow testing this library
 
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 8ffc043d816..1eaff7410ea 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -125,7 +125,7 @@ pub use core::slice::{from_ref, from_mut};
 pub use core::slice::SliceIndex;
 #[stable(feature = "chunks_exact", since = "1.31.0")]
 pub use core::slice::{ChunksExact, ChunksExactMut};
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut};
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 5a21976d75d..6d1cfb10859 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -19,7 +19,6 @@
 #![feature(str_escape)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(rchunks)]
 #![feature(repeat_generic_slice)]
 
 extern crate alloc_system;
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 628d5542ac0..8a6b212020b 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -795,8 +795,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
     /// let mut iter = slice.rchunks(2);
     /// assert_eq!(iter.next().unwrap(), &['e', 'm']);
@@ -807,7 +805,7 @@ impl<T> [T] {
     ///
     /// [`rchunks_exact`]: #method.rchunks_exact
     /// [`chunks`]: #method.chunks
-    #[unstable(feature = "rchunks", issue = "55177")]
+    #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks(&self, chunk_size: usize) -> RChunks<T> {
         assert!(chunk_size != 0);
@@ -831,8 +829,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -847,7 +843,7 @@ impl<T> [T] {
     ///
     /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut
     /// [`chunks_mut`]: #method.chunks_mut
-    #[unstable(feature = "rchunks", issue = "55177")]
+    #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<T> {
         assert!(chunk_size != 0);
@@ -875,8 +871,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
     /// let mut iter = slice.rchunks_exact(2);
     /// assert_eq!(iter.next().unwrap(), &['e', 'm']);
@@ -887,7 +881,7 @@ impl<T> [T] {
     ///
     /// [`rchunks`]: #method.rchunks
     /// [`chunks_exact`]: #method.chunks_exact
-    #[unstable(feature = "rchunks", issue = "55177")]
+    #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<T> {
         assert!(chunk_size != 0);
@@ -917,8 +911,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -933,7 +925,7 @@ impl<T> [T] {
     ///
     /// [`rchunks_mut`]: #method.rchunks_mut
     /// [`chunks_exact_mut`]: #method.chunks_exact_mut
-    #[unstable(feature = "rchunks", issue = "55177")]
+    #[stable(feature = "rchunks", since = "1.31.0")]
     #[inline]
     pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<T> {
         assert!(chunk_size != 0);
@@ -4256,14 +4248,14 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
 /// [`rchunks`]: ../../std/primitive.slice.html#method.rchunks
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunks<'a, T:'a> {
     v: &'a [T],
     chunk_size: usize
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Clone for RChunks<'a, T> {
     fn clone(&self) -> RChunks<'a, T> {
         RChunks {
@@ -4273,7 +4265,7 @@ impl<'a, T> Clone for RChunks<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Iterator for RChunks<'a, T> {
     type Item = &'a [T];
 
@@ -4337,7 +4329,7 @@ impl<'a, T> Iterator for RChunks<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -4353,17 +4345,17 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> ExactSizeIterator for RChunks<'a, T> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, T> TrustedLen for RChunks<'a, T> {}
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> FusedIterator for RChunks<'a, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
         let end = self.v.len() - i * self.chunk_size;
@@ -4387,13 +4379,13 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
 /// [`rchunks_mut`]: ../../std/primitive.slice.html#method.rchunks_mut
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksMut<'a, T:'a> {
     v: &'a mut [T],
     chunk_size: usize
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Iterator for RChunksMut<'a, T> {
     type Item = &'a mut [T];
 
@@ -4461,7 +4453,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -4478,17 +4470,17 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> ExactSizeIterator for RChunksMut<'a, T> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, T> TrustedLen for RChunksMut<'a, T> {}
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> FusedIterator for RChunksMut<'a, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
         let end = self.v.len() - i * self.chunk_size;
@@ -4514,25 +4506,25 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
 /// [`remainder`]: ../../std/slice/struct.ChunksExact.html#method.remainder
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksExact<'a, T:'a> {
     v: &'a [T],
     rem: &'a [T],
     chunk_size: usize
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
 impl<'a, T> RChunksExact<'a, T> {
     /// Return the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[stable(feature = "rchunks", since = "1.31.0")]
     pub fn remainder(&self) -> &'a [T] {
         self.rem
     }
 }
 
 // FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Clone for RChunksExact<'a, T> {
     fn clone(&self) -> RChunksExact<'a, T> {
         RChunksExact {
@@ -4543,7 +4535,7 @@ impl<'a, T> Clone for RChunksExact<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Iterator for RChunksExact<'a, T> {
     type Item = &'a [T];
 
@@ -4588,7 +4580,7 @@ impl<'a, T> Iterator for RChunksExact<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
@@ -4602,7 +4594,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4612,11 +4604,11 @@ impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, T> TrustedLen for RChunksExact<'a, T> {}
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> FusedIterator for RChunksExact<'a, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
         let end = self.v.len() - i * self.chunk_size;
@@ -4639,24 +4631,24 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
 /// [`into_remainder`]: ../../std/slice/struct.ChunksExactMut.html#method.into_remainder
 /// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksExactMut<'a, T:'a> {
     v: &'a mut [T],
     rem: &'a mut [T],
     chunk_size: usize
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
 impl<'a, T> RChunksExactMut<'a, T> {
     /// Return the remainder of the original slice that is not going to be
     /// returned by the iterator. The returned slice has at most `chunk_size-1`
     /// elements.
+    #[stable(feature = "rchunks", since = "1.31.0")]
     pub fn into_remainder(self) -> &'a mut [T] {
         self.rem
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> Iterator for RChunksExactMut<'a, T> {
     type Item = &'a mut [T];
 
@@ -4705,7 +4697,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
@@ -4720,7 +4712,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
     }
 }
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> ExactSizeIterator for RChunksExactMut<'a, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4730,11 +4722,11 @@ impl<'a, T> ExactSizeIterator for RChunksExactMut<'a, T> {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, T> TrustedLen for RChunksExactMut<'a, T> {}
 
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 impl<'a, T> FusedIterator for RChunksExactMut<'a, T> {}
 
 #[doc(hidden)]
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
 unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
     unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
         let end = self.v.len() - i * self.chunk_size;
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index affcdbea9d3..965bd545eed 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -34,7 +34,6 @@
 #![feature(trusted_len)]
 #![feature(try_from)]
 #![feature(try_trait)]
-#![feature(rchunks)]
 #![feature(align_offset)]
 #![feature(reverse_bits)]
 #![feature(inner_deref)]

From ef1a40d5fec8678c4ae51cf2dcbed96934182b8c Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Fri, 12 Oct 2018 15:16:29 +0100
Subject: [PATCH 16/16] Propagate bounds from generators

---
 .../borrow_check/nll/region_infer/mod.rs      | 12 ++++-------
 .../borrow_check/nll/type_check/mod.rs        | 15 ++++++-------
 .../borrow_check/nll/universal_regions.rs     |  4 ++--
 .../generator-region-requirements.ast.stderr  | 12 +++++++++++
 .../generator-region-requirements.nll.stderr  | 12 +++++++++++
 .../generator-region-requirements.rs          | 21 +++++++++++++++++++
 6 files changed, 57 insertions(+), 19 deletions(-)
 create mode 100644 src/test/ui/generator/generator-region-requirements.ast.stderr
 create mode 100644 src/test/ui/generator/generator-region-requirements.nll.stderr
 create mode 100644 src/test/ui/generator/generator-region-requirements.rs

diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index dd8a7f19a63..0fabcfe4564 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1268,7 +1268,7 @@ pub trait ClosureRegionRequirementsExt<'gcx, 'tcx> {
         tcx: TyCtxt<'_, 'gcx, 'tcx>,
         location: Location,
         closure_def_id: DefId,
-        closure_substs: ty::ClosureSubsts<'tcx>,
+        closure_substs: &'tcx ty::subst::Substs<'tcx>,
     ) -> Vec<QueryRegionConstraint<'tcx>>;
 
     fn subst_closure_mapping<T>(
@@ -1299,23 +1299,19 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
         tcx: TyCtxt<'_, 'gcx, 'tcx>,
         location: Location,
         closure_def_id: DefId,
-        closure_substs: ty::ClosureSubsts<'tcx>,
+        closure_substs: &'tcx ty::subst::Substs<'tcx>,
     ) -> Vec<QueryRegionConstraint<'tcx>> {
         debug!(
             "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
             location, closure_def_id, closure_substs
         );
 
-        // Get Tu.
-        let user_closure_ty = tcx.mk_closure(closure_def_id, closure_substs);
-        debug!("apply_requirements: user_closure_ty={:?}", user_closure_ty);
-
-        // Extract the values of the free regions in `user_closure_ty`
+        // Extract the values of the free regions in `closure_substs`
         // into a vector.  These are the regions that we will be
         // relating to one another.
         let closure_mapping = &UniversalRegions::closure_mapping(
             tcx,
-            user_closure_ty,
+            closure_substs,
             self.num_external_vids,
             tcx.closure_base_def_id(closure_def_id),
         );
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 1e79bc272e4..c5758cde949 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, UnpackedKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -2075,12 +2075,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             // desugaring. A closure gets desugared to a struct, and
             // these extra requirements are basically like where
             // clauses on the struct.
-            AggregateKind::Closure(def_id, substs) => {
-                self.prove_closure_bounds(tcx, *def_id, *substs, location)
-            }
-
-            AggregateKind::Generator(def_id, substs, _) => {
-                tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
+            AggregateKind::Closure(def_id, ty::ClosureSubsts { substs })
+            | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
+                self.prove_closure_bounds(tcx, *def_id, substs, location)
             }
 
             AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
@@ -2096,7 +2093,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         def_id: DefId,
-        substs: ty::ClosureSubsts<'tcx>,
+        substs: &'tcx Substs<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
         if let Some(closure_region_requirements) =
@@ -2155,7 +2152,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             );
         }
 
-        tcx.predicates_of(def_id).instantiate(tcx, substs.substs)
+        tcx.predicates_of(def_id).instantiate(tcx, substs)
     }
 
     fn prove_trait_ref(
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index eb6f1a0677b..c54a4f96b7d 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -232,13 +232,13 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// `V[1]: V[2]`.
     pub fn closure_mapping(
         tcx: TyCtxt<'_, '_, 'tcx>,
-        closure_ty: Ty<'tcx>,
+        closure_substs: &'tcx Substs<'tcx>,
         expected_num_vars: usize,
         closure_base_def_id: DefId,
     ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
         let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
         region_mapping.push(tcx.types.re_static);
-        tcx.for_each_free_region(&closure_ty, |fr| {
+        tcx.for_each_free_region(&closure_substs, |fr| {
             region_mapping.push(fr);
         });
 
diff --git a/src/test/ui/generator/generator-region-requirements.ast.stderr b/src/test/ui/generator/generator-region-requirements.ast.stderr
new file mode 100644
index 00000000000..6a423aea7ec
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.ast.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/generator-region-requirements.rs:15:51
+   |
+LL | fn dangle(x: &mut i32) -> &'static mut i32 {
+   |              -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
+...
+LL |             GeneratorState::Complete(c) => return c,
+   |                                                   ^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/generator/generator-region-requirements.nll.stderr b/src/test/ui/generator/generator-region-requirements.nll.stderr
new file mode 100644
index 00000000000..5d1050dc352
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.nll.stderr
@@ -0,0 +1,12 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/generator-region-requirements.rs:11:9
+   |
+LL | fn dangle(x: &mut i32) -> &'static mut i32 {
+   |              -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
+...
+LL |         x
+   |         ^ lifetime `'static` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/generator/generator-region-requirements.rs b/src/test/ui/generator/generator-region-requirements.rs
new file mode 100644
index 00000000000..59e7841309c
--- /dev/null
+++ b/src/test/ui/generator/generator-region-requirements.rs
@@ -0,0 +1,21 @@
+// revisions: ast nll
+// ignore-compare-mode-nll
+
+#![feature(generators, generator_trait)]
+#![cfg_attr(nll, feature(nll))]
+use std::ops::{Generator, GeneratorState};
+
+fn dangle(x: &mut i32) -> &'static mut i32 {
+    let mut g = || {
+        yield;
+        x
+    };
+    loop {
+        match unsafe { g.resume() } {
+            GeneratorState::Complete(c) => return c,
+            GeneratorState::Yielded(_) => (),
+        }
+    }
+}
+
+fn main() {}