diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 7d10ef3d28219..58606531a1ace 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1890,17 +1890,15 @@ where
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
         // Can't just add n + self.n due to overflow.
-        if self.n == 0 {
-            self.iter.nth(n)
-        } else {
+        if self.n > 0 {
             let to_skip = self.n;
             self.n = 0;
             // nth(n) skips n+1
             if self.iter.nth(to_skip - 1).is_none() {
                 return None;
             }
-            self.iter.nth(n)
         }
+        self.iter.nth(n)
     }
 
     #[inline]
@@ -1916,17 +1914,13 @@ where
 
     #[inline]
     fn last(mut self) -> Option<I::Item> {
-        if self.n == 0 {
-            self.iter.last()
-        } else {
-            let next = self.next();
-            if next.is_some() {
-                // recurse. n should be 0.
-                self.last().or(next)
-            } else {
-                None
+        if self.n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(self.n - 1).is_none() {
+                return None;
             }
         }
+        self.iter.last()
     }
 
     #[inline]
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index c721faafbecaf..a4f9193c0eb64 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -7,7 +7,7 @@ use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ItemLocalId};
 
-pub fn check_crate(hir_map: &Map<'_>) {
+pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
     hir_map.dep_graph.assert_ignored();
 
     let errors = Lock::new(Vec::new());
@@ -24,7 +24,7 @@ pub fn check_crate(hir_map: &Map<'_>) {
 
     if !errors.is_empty() {
         let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
-        bug!("{}", message);
+        sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
     }
 }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 1645420892a75..adda0cde24fc0 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -1235,7 +1235,7 @@ pub fn map_crate<'hir>(
     let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions };
 
     sess.time("validate_HIR_map", || {
-        hir_id_validator::check_crate(&map);
+        hir_id_validator::check_crate(&map, sess);
     });
 
     map
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index e1e774b853c20..055d70effc6e6 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -46,6 +46,7 @@
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 #![feature(hash_raw_entry)]
+#![feature(int_error_matching)]
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
index b33cde8e2af20..be530da5910df 100644
--- a/src/librustc/middle/recursion_limit.rs
+++ b/src/librustc/middle/recursion_limit.rs
@@ -6,26 +6,60 @@
 // just peeks and looks for that attribute.
 
 use crate::session::Session;
+use core::num::IntErrorKind;
+use rustc::bug;
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast;
 
 use rustc_data_structures::sync::Once;
 
 pub fn update_limits(sess: &Session, krate: &ast::Crate) {
-    update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 128);
-    update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
+    update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
+    update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
 }
 
-fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: Symbol, default: usize) {
+fn update_limit(
+    sess: &Session,
+    krate: &ast::Crate,
+    limit: &Once<usize>,
+    name: Symbol,
+    default: usize,
+) {
     for attr in &krate.attrs {
         if !attr.check_name(name) {
             continue;
         }
 
         if let Some(s) = attr.value_str() {
-            if let Some(n) = s.as_str().parse().ok() {
-                limit.set(n);
-                return;
+            match s.as_str().parse() {
+                Ok(n) => {
+                    limit.set(n);
+                    return;
+                }
+                Err(e) => {
+                    let mut err = sess.struct_span_err(
+                        attr.span,
+                        "`recursion_limit` must be a non-negative integer",
+                    );
+
+                    let value_span = attr
+                        .meta()
+                        .and_then(|meta| meta.name_value_literal().cloned())
+                        .map(|lit| lit.span)
+                        .unwrap_or(attr.span);
+
+                    let error_str = match e.kind() {
+                        IntErrorKind::Overflow => "`recursion_limit` is too large",
+                        IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer",
+                        IntErrorKind::InvalidDigit => "not a valid integer",
+                        IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"),
+                        IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"),
+                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
+                    };
+
+                    err.span_label(value_span, error_str);
+                    err.emit();
+                }
             }
         }
     }
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 3ca778354e413..674d4c7113801 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -255,8 +255,9 @@ pub mod guard {
 
     #[cfg(target_os = "macos")]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize
-            - libc::pthread_get_stacksize_np(libc::pthread_self());
+        let th = libc::pthread_self();
+        let stackaddr =
+            libc::pthread_get_stackaddr_np(th) as usize - libc::pthread_get_stacksize_np(th);
         Some(stackaddr as *mut libc::c_void)
     }
 
diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs
index 8c5f67a66043e..bc4fac3183cea 100644
--- a/src/test/debuginfo/empty-string.rs
+++ b/src/test/debuginfo/empty-string.rs
@@ -2,6 +2,7 @@
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
 // min-gdb-version: 7.7
+// ignore-gdb-version: 7.11.90 - 8.0.9
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
diff --git a/src/test/ui/generator/async-generator-issue-67158.rs b/src/test/ui/generator/async-generator-issue-67158.rs
new file mode 100644
index 0000000000000..8125a7a9bb664
--- /dev/null
+++ b/src/test/ui/generator/async-generator-issue-67158.rs
@@ -0,0 +1,6 @@
+#![feature(generators)]
+// edition:2018
+// Regression test for #67158.
+fn main() {
+    async { yield print!(":C") }; //~ ERROR `async` generators are not yet supported
+}
diff --git a/src/test/ui/generator/async-generator-issue-67158.stderr b/src/test/ui/generator/async-generator-issue-67158.stderr
new file mode 100644
index 0000000000000..7270d188e8b88
--- /dev/null
+++ b/src/test/ui/generator/async-generator-issue-67158.stderr
@@ -0,0 +1,9 @@
+error[E0727]: `async` generators are not yet supported
+  --> $DIR/async-generator-issue-67158.rs:5:13
+   |
+LL |     async { yield print!(":C") };
+   |             ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0727`.
diff --git a/src/test/ui/recursion_limit/empty.rs b/src/test/ui/recursion_limit/empty.rs
new file mode 100644
index 0000000000000..2a064f3e11599
--- /dev/null
+++ b/src/test/ui/recursion_limit/empty.rs
@@ -0,0 +1,6 @@
+// Test the parse error for an empty recursion_limit
+
+#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer
+                         //~| `recursion_limit` must be a non-negative integer
+
+fn main() {}
diff --git a/src/test/ui/recursion_limit/empty.stderr b/src/test/ui/recursion_limit/empty.stderr
new file mode 100644
index 0000000000000..690c33a746307
--- /dev/null
+++ b/src/test/ui/recursion_limit/empty.stderr
@@ -0,0 +1,10 @@
+error: `recursion_limit` must be a non-negative integer
+  --> $DIR/empty.rs:3:1
+   |
+LL | #![recursion_limit = ""]
+   | ^^^^^^^^^^^^^^^^^^^^^--^
+   |                      |
+   |                      `recursion_limit` must be a non-negative integer
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/recursion_limit/invalid_digit.rs b/src/test/ui/recursion_limit/invalid_digit.rs
new file mode 100644
index 0000000000000..903d804047696
--- /dev/null
+++ b/src/test/ui/recursion_limit/invalid_digit.rs
@@ -0,0 +1,6 @@
+// Test the parse error for an invalid digit in recursion_limit
+
+#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer
+                             //~| not a valid integer
+
+fn main() {}
diff --git a/src/test/ui/recursion_limit/invalid_digit.stderr b/src/test/ui/recursion_limit/invalid_digit.stderr
new file mode 100644
index 0000000000000..1dcfea547c0bd
--- /dev/null
+++ b/src/test/ui/recursion_limit/invalid_digit.stderr
@@ -0,0 +1,10 @@
+error: `recursion_limit` must be a non-negative integer
+  --> $DIR/invalid_digit.rs:3:1
+   |
+LL | #![recursion_limit = "-100"]
+   | ^^^^^^^^^^^^^^^^^^^^^------^
+   |                      |
+   |                      not a valid integer
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/recursion_limit/overflow.rs b/src/test/ui/recursion_limit/overflow.rs
new file mode 100644
index 0000000000000..6487b1350aa98
--- /dev/null
+++ b/src/test/ui/recursion_limit/overflow.rs
@@ -0,0 +1,7 @@
+// Test the parse error for an overflowing recursion_limit
+
+#![recursion_limit = "999999999999999999999999"]
+//~^ ERROR `recursion_limit` must be a non-negative integer
+//~| `recursion_limit` is too large
+
+fn main() {}
diff --git a/src/test/ui/recursion_limit/overflow.stderr b/src/test/ui/recursion_limit/overflow.stderr
new file mode 100644
index 0000000000000..c3fc11989dcec
--- /dev/null
+++ b/src/test/ui/recursion_limit/overflow.stderr
@@ -0,0 +1,10 @@
+error: `recursion_limit` must be a non-negative integer
+  --> $DIR/overflow.rs:3:1
+   |
+LL | #![recursion_limit = "999999999999999999999999"]
+   | ^^^^^^^^^^^^^^^^^^^^^--------------------------^
+   |                      |
+   |                      `recursion_limit` is too large
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/recursion_limit/zero.rs b/src/test/ui/recursion_limit/zero.rs
new file mode 100644
index 0000000000000..f7199944e0063
--- /dev/null
+++ b/src/test/ui/recursion_limit/zero.rs
@@ -0,0 +1,12 @@
+// Test that a `recursion_limit` of 0 is valid
+
+#![recursion_limit = "0"]
+
+macro_rules! test {
+    () => {};
+    ($tt:tt) => { test!(); };
+}
+
+test!(test); //~ ERROR 10:1: 10:13: recursion limit reached while expanding `test!`
+
+fn main() {}
diff --git a/src/test/ui/recursion_limit/zero.stderr b/src/test/ui/recursion_limit/zero.stderr
new file mode 100644
index 0000000000000..6358805d89dee
--- /dev/null
+++ b/src/test/ui/recursion_limit/zero.stderr
@@ -0,0 +1,10 @@
+error: recursion limit reached while expanding `test!`
+  --> $DIR/zero.rs:10:1
+   |
+LL | test!(test);
+   | ^^^^^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="0"]` attribute to your crate (`zero`)
+
+error: aborting due to previous error
+