about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rw-r--r--src/libcore/num/mod.rs56
-rw-r--r--src/libcore/pin.rs34
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/num/int_macros.rs26
-rw-r--r--src/librustc/cfg/construct.rs1
-rw-r--r--src/librustc/error_codes.rs30
-rw-r--r--src/librustc/hir/intravisit.rs3
-rw-r--r--src/librustc/hir/lowering.rs45
-rw-r--r--src/librustc/hir/mod.rs6
-rw-r--r--src/librustc/hir/print.rs53
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs44
-rw-r--r--src/librustc/infer/mod.rs7
-rw-r--r--src/librustc/infer/resolve.rs36
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/expr_use_visitor.rs4
-rw-r--r--src/librustc/middle/liveness.rs8
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/region.rs6
-rw-r--r--src/librustc/mir/mod.rs138
-rw-r--r--src/librustc/traits/project.rs6
-rw-r--r--src/librustc/traits/select.rs14
-rw-r--r--src/librustc_lint/builtin.rs16
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs3
-rw-r--r--src/librustc_passes/rvalue_promotion.rs9
-rw-r--r--src/librustc_resolve/error_codes.rs13
-rw-r--r--src/librustc_resolve/lib.rs44
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/builtin.rs168
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/mod.rs21
-rw-r--r--src/librustc_typeck/check/generator_interior.rs16
-rw-r--r--src/librustc_typeck/check/mod.rs3
-rw-r--r--src/librustc_typeck/check/op.rs16
-rw-r--r--src/librustc_typeck/error_codes.rs1
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/html/render.rs44
-rw-r--r--src/libsyntax/feature_gate.rs35
-rw-r--r--src/test/run-pass/chalkify/builtin-copy-clone.rs43
-rw-r--r--src/test/rustdoc-ui/cfg-test.rs19
-rw-r--r--src/test/rustdoc-ui/cfg-test.stdout6
-rw-r--r--src/test/rustdoc/index-page.rs3
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs6
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr19
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.rs13
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr24
-rw-r--r--src/test/ui/feature-gate/allow-features-empty.rs2
-rw-r--r--src/test/ui/feature-gate/allow-features-empty.stderr8
-rw-r--r--src/test/ui/feature-gate/allow-features.rs2
-rw-r--r--src/test/ui/feature-gate/allow-features.stderr8
-rw-r--r--src/test/ui/generator/unresolved_type_param.rs14
-rw-r--r--src/test/ui/generator/unresolved_type_param.stderr16
-rw-r--r--src/test/ui/target-feature-gate.rs1
-rw-r--r--src/test/ui/target-feature-gate.stderr2
54 files changed, 858 insertions, 253 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e9f234a95c6..9c2531097bf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1523,7 +1523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "minifier"
-version = "0.0.29"
+version = "0.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3038,7 +3038,7 @@ dependencies = [
 name = "rustdoc"
 version = "0.0.0"
 dependencies = [
- "minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4170,7 +4170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4950cb2617b1933e2da0446e864dfe0d6a22c22ff72297996c46e6a63b210b"
+"checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0"
 "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
 "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
 "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 5c48c732b78..c1887a93490 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -961,6 +961,62 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN`
+instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "#![feature(saturating_neg)]
+assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100);
+assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100);
+assert_eq!(", stringify!($SelfT), "::min_value().saturating_neg(), ", stringify!($SelfT),
+"::max_value());
+assert_eq!(", stringify!($SelfT), "::max_value().saturating_neg(), ", stringify!($SelfT),
+"::min_value() + 1);",
+$EndFeature, "
+```"),
+
+            #[unstable(feature = "saturating_neg", issue = "59983")]
+            #[inline]
+            pub fn saturating_neg(self) -> Self {
+                intrinsics::saturating_sub(0, self)
+            }
+        }
+
+        doc_comment! {
+            concat!("Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self ==
+MIN` instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "#![feature(saturating_neg)]
+assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100);
+assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100);
+assert_eq!(", stringify!($SelfT), "::min_value().saturating_abs(), ", stringify!($SelfT),
+"::max_value());
+assert_eq!((", stringify!($SelfT), "::min_value() + 1).saturating_abs(), ", stringify!($SelfT),
+"::max_value());",
+$EndFeature, "
+```"),
+
+            #[unstable(feature = "saturating_neg", issue = "59983")]
+            #[inline]
+            pub fn saturating_abs(self) -> Self {
+                if self.is_negative() {
+                    self.saturating_neg()
+                } else {
+                    self
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Saturating integer multiplication. Computes `self * rhs`, saturating at the
 numeric bounds instead of overflowing.
 
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index dbf3dcf03a3..e74ed9b7889 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -349,6 +349,18 @@ where
         // around pinning.
         unsafe { Pin::new_unchecked(pointer) }
     }
+
+    /// Unwraps this `Pin<P>` returning the underlying pointer.
+    ///
+    /// This requires that the data inside this `Pin` is [`Unpin`] so that we
+    /// can ignore the pinning invariants when unwrapping it.
+    ///
+    /// [`Unpin`]: ../../std/marker/trait.Unpin.html
+    #[unstable(feature = "pin_into_inner", issue = "60245")]
+    #[inline(always)]
+    pub fn into_inner(pin: Pin<P>) -> P {
+        pin.pointer
+    }
 }
 
 impl<P: Deref> Pin<P> {
@@ -434,6 +446,28 @@ impl<P: Deref> Pin<P> {
     pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
         unsafe { Pin::new_unchecked(&*self.pointer) }
     }
+
+    /// Unwraps this `Pin<P>` returning the underlying pointer.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe. You must guarantee that you will continue to
+    /// treat the pointer `P` as pinned after you call this function, so that
+    /// the invariants on the `Pin` type can be upheld. If the code using the
+    /// resulting `P` does not continue to maintain the pinning invariants that
+    /// is a violation of the API contract and may lead to undefined behavior in
+    /// later (safe) operations.
+    ///
+    /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
+    /// instead.
+    ///
+    /// [`Unpin`]: ../../std/marker/trait.Unpin.html
+    /// [`Pin::into_inner`]: #method.into_inner
+    #[unstable(feature = "pin_into_inner", issue = "60245")]
+    #[inline(always)]
+    pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
+        pin.pointer
+    }
 }
 
 impl<P: DerefMut> Pin<P> {
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 2e4a8a15d20..a3d294e77d3 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -16,6 +16,7 @@
 #![feature(pattern)]
 #![feature(range_is_empty)]
 #![feature(raw)]
+#![feature(saturating_neg)]
 #![feature(slice_patterns)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
index 92409465d7f..0475aeb96ab 100644
--- a/src/libcore/tests/num/int_macros.rs
+++ b/src/libcore/tests/num/int_macros.rs
@@ -154,6 +154,32 @@ mod tests {
     }
 
     #[test]
+    fn test_saturating_abs() {
+        assert_eq!((0 as $T).saturating_abs(), 0);
+        assert_eq!((123 as $T).saturating_abs(), 123);
+        assert_eq!((-123 as $T).saturating_abs(), 123);
+        assert_eq!((MAX - 2).saturating_abs(), MAX - 2);
+        assert_eq!((MAX - 1).saturating_abs(), MAX - 1);
+        assert_eq!(MAX.saturating_abs(), MAX);
+        assert_eq!((MIN + 2).saturating_abs(), MAX - 1);
+        assert_eq!((MIN + 1).saturating_abs(), MAX);
+        assert_eq!(MIN.saturating_abs(), MAX);
+    }
+
+    #[test]
+    fn test_saturating_neg() {
+        assert_eq!((0 as $T).saturating_neg(), 0);
+        assert_eq!((123 as $T).saturating_neg(), -123);
+        assert_eq!((-123 as $T).saturating_neg(), 123);
+        assert_eq!((MAX - 2).saturating_neg(), MIN + 3);
+        assert_eq!((MAX - 1).saturating_neg(), MIN + 2);
+        assert_eq!(MAX.saturating_neg(), MIN + 1);
+        assert_eq!((MIN + 2).saturating_neg(), MAX - 1);
+        assert_eq!((MIN + 1).saturating_neg(), MAX);
+        assert_eq!(MIN.saturating_neg(), MAX);
+    }
+
+    #[test]
     fn test_from_str() {
         fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
             ::std::str::FromStr::from_str(t).ok()
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index e96709f6d14..8a4594fe0e8 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -369,6 +369,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             hir::ExprKind::AddrOf(_, ref e) |
             hir::ExprKind::Cast(ref e, _) |
             hir::ExprKind::Type(ref e, _) |
+            hir::ExprKind::Use(ref e) |
             hir::ExprKind::Unary(_, ref e) |
             hir::ExprKind::Field(ref e, _) |
             hir::ExprKind::Yield(ref e) |
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index 00f9fa3a938..f6917c45d57 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -2043,6 +2043,36 @@ a (non-transparent) struct containing a single float, while `Grams` is a
 transparent wrapper around a float. This can make a difference for the ABI.
 "##,
 
+E0698: r##"
+When using generators (or async) all type variables must be bound so a
+generator can be constructed.
+
+Erroneous code example:
+
+```edition2018,compile-fail,E0698
+#![feature(futures_api, async_await, await_macro)]
+async fn bar<T>() -> () {}
+
+async fn foo() {
+  await!(bar());  // error: cannot infer type for `T`
+}
+```
+
+In the above example `T` is unknowable by the compiler.
+To fix this you must bind `T` to a concrete type such as `String`
+so that a generator can then be constructed:
+
+```edition2018
+#![feature(futures_api, async_await, await_macro)]
+async fn bar<T>() -> () {}
+
+async fn foo() {
+  await!(bar::<String>());
+  //          ^^^^^^^^ specify type explicitly
+}
+```
+"##,
+
 E0700: r##"
 The `impl Trait` return type captures lifetime parameters that do not
 appear within the `impl Trait` itself.
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index a0c9e5983a1..3d727f7cd91 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -1029,6 +1029,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_ty(typ)
         }
+        ExprKind::Use(ref subexpression) => {
+            visitor.visit_expr(subexpression);
+        }
         ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
             visitor.visit_expr(head_expression);
             visitor.visit_expr(if_block);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d4dd983e217..bcf1b30814f 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4740,16 +4740,11 @@ impl<'a> LoweringContext<'a> {
                     hir::MatchSource::ForLoopDesugar,
                 ));
 
-                // `{ let _result = ...; _result }`
-                // Underscore prevents an `unused_variables` lint if the head diverges.
-                let result_ident = self.str_to_ident("_result");
-                let (let_stmt, let_stmt_binding) =
-                    self.stmt_let(e.span, false, result_ident, match_expr);
-
-                let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
-                let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
-                // Add the attributes to the outer returned expr node.
-                return self.expr_block(block, e.attrs.clone());
+                // This is effectively `{ let _result = ...; _result }`.
+                // The construct was introduced in #21984.
+                // FIXME(60253): Is this still necessary?
+                // Also, add the attributes to the outer returned expr node.
+                return self.expr_use(head_sp, match_expr, e.attrs.clone())
             }
 
             // Desugar `ExprKind::Try`
@@ -5119,6 +5114,17 @@ impl<'a> LoweringContext<'a> {
         )
     }
 
+    /// Wrap the given `expr` in `hir::ExprKind::Use`.
+    ///
+    /// In terms of drop order, it has the same effect as
+    /// wrapping `expr` in `{ let _t = $expr; _t }` but
+    /// should provide better compile-time performance.
+    ///
+    /// The drop order can be important in e.g. `if expr { .. }`.
+    fn expr_use(&mut self, span: Span, expr: P<hir::Expr>, attrs: ThinVec<Attribute>) -> hir::Expr {
+        self.expr(span, hir::ExprKind::Use(expr), attrs)
+    }
+
     fn expr_match(
         &mut self,
         span: Span,
@@ -5174,25 +5180,6 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn stmt_let(
-        &mut self,
-        sp: Span,
-        mutbl: bool,
-        ident: Ident,
-        ex: P<hir::Expr>,
-    ) -> (hir::Stmt, hir::HirId) {
-        let (pat, pat_hid) = if mutbl {
-            self.pat_ident_binding_mode(sp, ident, hir::BindingAnnotation::Mutable)
-        } else {
-            self.pat_ident(sp, ident)
-        };
-
-        (
-            self.stmt_let_pat(sp, Some(ex), pat, hir::LocalSource::Normal),
-            pat_hid,
-        )
-    }
-
     fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
         self.block_all(expr.span, hir::HirVec::new(), Some(expr))
     }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f114f0fc236..2e10300dced 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1366,6 +1366,7 @@ impl Expr {
             ExprKind::Unary(..) => ExprPrecedence::Unary,
             ExprKind::Lit(_) => ExprPrecedence::Lit,
             ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
+            ExprKind::Use(ref expr, ..) => expr.precedence(),
             ExprKind::If(..) => ExprPrecedence::If,
             ExprKind::While(..) => ExprPrecedence::While,
             ExprKind::Loop(..) => ExprPrecedence::Loop,
@@ -1437,6 +1438,7 @@ impl Expr {
             ExprKind::Binary(..) |
             ExprKind::Yield(..) |
             ExprKind::Cast(..) |
+            ExprKind::Use(..) |
             ExprKind::Err => {
                 false
             }
@@ -1486,6 +1488,10 @@ pub enum ExprKind {
     Cast(P<Expr>, P<Ty>),
     /// A type reference (e.g., `Foo`).
     Type(P<Expr>, P<Ty>),
+    /// Semantically equivalent to `{ let _t = expr; _t }`.
+    /// Maps directly to `hair::ExprKind::Use`.
+    /// Only exists to tweak the drop order in HIR.
+    Use(P<Expr>),
     /// An `if` block, with an optional else block.
     ///
     /// I.e., `if <expr> { <expr> } else { <expr> }`.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index dc87e13b739..06225364f6c 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -995,23 +995,32 @@ impl<'a> State<'a> {
         self.ann.post(self, AnnNode::SubItem(ii.hir_id))
     }
 
+    pub fn print_local(
+        &mut self,
+        init: Option<&hir::Expr>,
+        decl: impl Fn(&mut Self) -> io::Result<()>
+    ) -> io::Result<()> {
+        self.space_if_not_bol()?;
+        self.ibox(indent_unit)?;
+        self.word_nbsp("let")?;
+
+        self.ibox(indent_unit)?;
+        decl(self)?;
+        self.end()?;
+
+        if let Some(ref init) = init {
+            self.nbsp()?;
+            self.word_space("=")?;
+            self.print_expr(&init)?;
+        }
+        self.end()
+    }
+
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
         self.maybe_print_comment(st.span.lo())?;
         match st.node {
             hir::StmtKind::Local(ref loc) => {
-                self.space_if_not_bol()?;
-                self.ibox(indent_unit)?;
-                self.word_nbsp("let")?;
-
-                self.ibox(indent_unit)?;
-                self.print_local_decl(&loc)?;
-                self.end()?;
-                if let Some(ref init) = loc.init {
-                    self.nbsp()?;
-                    self.word_space("=")?;
-                    self.print_expr(&init)?;
-                }
-                self.end()?
+                self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc))?;
             }
             hir::StmtKind::Item(item) => {
                 self.ann.nested(self, Nested::Item(item))?
@@ -1379,6 +1388,24 @@ impl<'a> State<'a> {
                 self.word_space(":")?;
                 self.print_type(&ty)?;
             }
+            hir::ExprKind::Use(ref init) => {
+                // Print `{`:
+                self.cbox(indent_unit)?;
+                self.ibox(0)?;
+                self.bopen()?;
+
+                // Print `let _t = $init;`:
+                let temp = ast::Ident::from_str("_t");
+                self.print_local(Some(init), |this| this.print_ident(temp))?;
+                self.s.word(";")?;
+
+                // Print `_t`:
+                self.space_if_not_bol()?;
+                self.print_ident(temp)?;
+
+                // Print `}`:
+                self.bclose_maybe_open(expr.span, indent_unit, true)?;
+            }
             hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
                 self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
             }
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 0a83b839201..2c01e1c0de3 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -88,23 +88,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         s
     }
 
-    pub fn need_type_info_err(&self,
-                            body_id: Option<hir::BodyId>,
-                            span: Span,
-                            ty: Ty<'tcx>)
-                            -> DiagnosticBuilder<'gcx> {
+    pub fn need_type_info_err(
+        &self,
+        body_id: Option<hir::BodyId>,
+        span: Span,
+        ty: Ty<'tcx>
+    ) -> DiagnosticBuilder<'gcx> {
         let ty = self.resolve_type_vars_if_possible(&ty);
         let name = self.extract_type_name(&ty, None);
 
         let mut err_span = span;
-        let mut labels = vec![(
-            span,
-            if &name == "_" {
-                "cannot infer type".to_owned()
-            } else {
-                format!("cannot infer type for `{}`", name)
-            },
-        )];
+        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
 
         let mut local_visitor = FindLocalByTypeVisitor {
             infcx: &self,
@@ -166,4 +160,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
         err
     }
+
+    pub fn need_type_info_err_in_generator(
+        &self,
+        span: Span,
+        ty: Ty<'tcx>
+    ) -> DiagnosticBuilder<'gcx> {
+        let ty = self.resolve_type_vars_if_possible(&ty);
+        let name = self.extract_type_name(&ty, None);
+
+        let mut err = struct_span_err!(self.tcx.sess,
+                       span,
+                       E0698,
+                       "type inside generator must be known in this context");
+        err.span_label(span, InferCtxt::missing_type_msg(&name));
+        err
+    }
+
+    fn missing_type_msg(type_name: &str) -> String {
+        if type_name == "_" {
+            "cannot infer type".to_owned()
+        } else {
+            format!("cannot infer type for `{}`", type_name)
+        }
+    }
 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f3325034351..e9b80c56e0c 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1309,17 +1309,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         value.fold_with(&mut r)
     }
 
-    /// Returns `true` if `T` contains unresolved type variables. In the
+    /// Returns first unresolved variable contained in `T`. In the
     /// process of visiting `T`, this will resolve (where possible)
     /// type variables in `T`, but it never constructs the final,
     /// resolved type, so it's more efficient than
     /// `resolve_type_vars_if_possible()`.
-    pub fn any_unresolved_type_vars<T>(&self, value: &T) -> bool
+    pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
     where
         T: TypeFoldable<'tcx>,
     {
         let mut r = resolve::UnresolvedTypeFinder::new(self);
-        value.visit_with(&mut r)
+        value.visit_with(&mut r);
+        r.first_unresolved
     }
 
     pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs
index 4a8f0c34ead..6adbf2bcef8 100644
--- a/src/librustc/infer/resolve.rs
+++ b/src/librustc/infer/resolve.rs
@@ -1,4 +1,4 @@
-use super::{InferCtxt, FixupError, FixupResult};
+use super::{InferCtxt, FixupError, FixupResult, Span, type_variable::TypeVariableOrigin};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::fold::{TypeFolder, TypeVisitor};
 
@@ -77,17 +77,20 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeAndRegionResolv
 ///////////////////////////////////////////////////////////////////////////
 // UNRESOLVED TYPE FINDER
 
-/// The unresolved type **finder** walks your type and searches for
-/// type variables that don't yet have a value. They get pushed into a
-/// vector. It does not construct the fully resolved type (which might
+/// The unresolved type **finder** walks a type searching for
+/// type variables that don't yet have a value. The first unresolved type is stored.
+/// It does not construct the fully resolved type (which might
 /// involve some hashing and so forth).
 pub struct UnresolvedTypeFinder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+
+    /// Used to find the type parameter name and location for error reporting.
+    pub first_unresolved: Option<(Ty<'tcx>,Option<Span>)>,
 }
 
 impl<'a, 'gcx, 'tcx> UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
-        UnresolvedTypeFinder { infcx }
+        UnresolvedTypeFinder { infcx, first_unresolved: None }
     }
 }
 
@@ -95,22 +98,37 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx>
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         let t = self.infcx.shallow_resolve(t);
         if t.has_infer_types() {
-            if let ty::Infer(_) = t.sty {
+            if let ty::Infer(infer_ty) = t.sty {
                 // Since we called `shallow_resolve` above, this must
                 // be an (as yet...) unresolved inference variable.
-                true
+                let ty_var_span =
+                if let ty::TyVar(ty_vid) = infer_ty {
+                    let ty_vars = self.infcx.type_variables.borrow();
+                    if let TypeVariableOrigin::TypeParameterDefinition(span, _name)
+                        = *ty_vars.var_origin(ty_vid)
+                    {
+                        Some(span)
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                };
+                self.first_unresolved = Some((t, ty_var_span));
+                true  // Halt visiting.
             } else {
                 // Otherwise, visit its contents.
                 t.super_visit_with(self)
             }
         } else {
-            // Micro-optimize: no inference types at all Can't have unresolved type
-            // variables, no need to visit the contents.
+            // All type variables in inference types must already be resolved,
+            // - no need to visit the contents, continue visiting.
             false
         }
     }
 }
 
+
 ///////////////////////////////////////////////////////////////////////////
 // FULL TYPE RESOLUTION
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 1bd44b13b66..920f9780543 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -37,6 +37,7 @@
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
+#![feature(inner_deref)]
 #![cfg_attr(windows, feature(libc))]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 217af7eea96..52f105b8c40 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -521,6 +521,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 self.consume_expr(&base);
             }
 
+            hir::ExprKind::Use(ref expr) => {
+                self.consume_expr(&expr);
+            }
+
             hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => {
                 if self.mc.tables.is_method_call(expr) {
                     self.consume_expr(lhs);
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index b8cde936bde..966bec8381a 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -521,6 +521,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
       hir::ExprKind::Binary(..) |
       hir::ExprKind::AddrOf(..) |
       hir::ExprKind::Cast(..) |
+      hir::ExprKind::Use(..) |
       hir::ExprKind::Unary(..) |
       hir::ExprKind::Break(..) |
       hir::ExprKind::Continue(_) |
@@ -1221,6 +1222,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             hir::ExprKind::AddrOf(_, ref e) |
             hir::ExprKind::Cast(ref e, _) |
             hir::ExprKind::Type(ref e, _) |
+            hir::ExprKind::Use(ref e) |
             hir::ExprKind::Unary(_, ref e) |
             hir::ExprKind::Yield(ref e) |
             hir::ExprKind::Repeat(ref e, _) => {
@@ -1524,9 +1526,9 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
         hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) |
         hir::ExprKind::Index(..) | hir::ExprKind::Field(..) |
         hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) |
-        hir::ExprKind::Cast(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) |
-        hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) |
-        hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
+        hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | hir::ExprKind::Unary(..) |
+        hir::ExprKind::Ret(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) |
+        hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
         hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
         hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
         hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index a4a54ba1837..25fa19558de 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -678,7 +678,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) |
             hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) |
             hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) |
-            hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) |
+            hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) |
             hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) |
             hir::ExprKind::Binary(..) | hir::ExprKind::While(..) |
             hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 2b380238810..9a5af8a2537 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -909,6 +909,12 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
                 visitor.cx.var_parent = visitor.cx.parent;
             }
 
+            hir::ExprKind::Use(ref expr) => {
+                // `Use(expr)` does not denote a conditional scope.
+                // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
+                terminating(expr.hir_id.local_id);
+            }
+
             hir::ExprKind::AssignOp(..) | hir::ExprKind::Index(..) |
             hir::ExprKind::Unary(..) | hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => {
                 // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 9da961b4e9e..0dc23f5ce47 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2158,61 +2158,95 @@ impl<'p, 'tcx> FusedIterator for PlaceProjectionsIter<'p, 'tcx> {}
 
 impl<'tcx> Debug for Place<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
-        use self::Place::*;
-
-        match *self {
-            Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
-            Base(PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) })) => {
-                write!(
-                    fmt,
-                    "({}: {:?})",
-                    ty::tls::with(|tcx| tcx.def_path_str(def_id)),
-                    ty
-                )
-            },
-            Base(PlaceBase::Static(
-                box self::Static { ty, kind: StaticKind::Promoted(promoted) })
-            ) => {
-                write!(
-                    fmt,
-                    "({:?}: {:?})",
-                    promoted,
-                    ty
-                )
-            },
-            Projection(ref data) => match data.elem {
-                ProjectionElem::Downcast(Some(name), _index) => {
-                    write!(fmt, "({:?} as {})", data.base, name)
-                }
-                ProjectionElem::Downcast(None, index) => {
-                    write!(fmt, "({:?} as variant#{:?})", data.base, index)
-                }
-                ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
-                ProjectionElem::Field(field, ty) => {
-                    write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty)
-                }
-                ProjectionElem::Index(ref index) => write!(fmt, "{:?}[{:?}]", data.base, index),
-                ProjectionElem::ConstantIndex {
-                    offset,
-                    min_length,
-                    from_end: false,
-                } => write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length),
-                ProjectionElem::ConstantIndex {
-                    offset,
-                    min_length,
-                    from_end: true,
-                } => write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length),
-                ProjectionElem::Subslice { from, to } if to == 0 => {
-                    write!(fmt, "{:?}[{:?}:]", data.base, from)
+        self.iterate(|_place_base, place_projections| {
+            // FIXME: remove this collect once we have migrated to slices
+            let projs_vec: Vec<_> = place_projections.collect();
+            for projection in projs_vec.iter().rev() {
+                match projection.elem {
+                    ProjectionElem::Downcast(_, _) |
+                    ProjectionElem::Field(_, _) => {
+                        write!(fmt, "(").unwrap();
+                    }
+                    ProjectionElem::Deref => {
+                        write!(fmt, "(*").unwrap();
+                    }
+                    ProjectionElem::Index(_) |
+                    ProjectionElem::ConstantIndex { .. } |
+                    ProjectionElem::Subslice { .. } => {}
                 }
-                ProjectionElem::Subslice { from, to } if from == 0 => {
-                    write!(fmt, "{:?}[:-{:?}]", data.base, to)
+            }
+        });
+
+        self.iterate(|place_base, place_projections| {
+            match place_base {
+                PlaceBase::Local(id) => {
+                    write!(fmt, "{:?}", id)?;
                 }
-                ProjectionElem::Subslice { from, to } => {
-                    write!(fmt, "{:?}[{:?}:-{:?}]", data.base, from, to)
+                PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => {
+                    write!(
+                        fmt,
+                        "({}: {:?})",
+                        ty::tls::with(|tcx| tcx.def_path_str(*def_id)),
+                        ty
+                    )?;
+                },
+                PlaceBase::Static(
+                    box self::Static { ty, kind: StaticKind::Promoted(promoted) }
+                ) => {
+                    write!(
+                        fmt,
+                        "({:?}: {:?})",
+                        promoted,
+                        ty
+                    )?;
+                },
+            }
+
+            for projection in place_projections {
+                match projection.elem {
+                    ProjectionElem::Downcast(Some(name), _index) => {
+                        write!(fmt, " as {})", name)?;
+                    }
+                    ProjectionElem::Downcast(None, index) => {
+                        write!(fmt, " as variant#{:?})", index)?;
+                    }
+                    ProjectionElem::Deref => {
+                        write!(fmt, ")")?;
+                    }
+                    ProjectionElem::Field(field, ty) => {
+                        write!(fmt, ".{:?}: {:?})", field.index(), ty)?;
+                    }
+                    ProjectionElem::Index(ref index) => {
+                        write!(fmt, "[{:?}]", index)?;
+                    }
+                    ProjectionElem::ConstantIndex {
+                        offset,
+                        min_length,
+                        from_end: false,
+                    } => {
+                        write!(fmt, "[{:?} of {:?}]", offset, min_length)?;
+                    }
+                    ProjectionElem::ConstantIndex {
+                        offset,
+                        min_length,
+                        from_end: true,
+                    } => {
+                        write!(fmt, "[-{:?} of {:?}]", offset, min_length)?;
+                    }
+                    ProjectionElem::Subslice { from, to } if to == 0 => {
+                        write!(fmt, "[{:?}:]", from)?;
+                    }
+                    ProjectionElem::Subslice { from, to } if from == 0 => {
+                        write!(fmt, "[:-{:?}]", to)?;
+                    }
+                    ProjectionElem::Subslice { from, to } => {
+                        write!(fmt, "[{:?}:-{:?}]", from, to)?;
+                    }
                 }
-            },
-        }
+            }
+
+            Ok(())
+        })
     }
 }
 
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 360e2323b64..882635e21f5 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -594,7 +594,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
 
             // Once we have inferred everything we need to know, we
             // can ignore the `obligations` from that point on.
-            if !infcx.any_unresolved_type_vars(&ty.value) {
+            if infcx.unresolved_type_vars(&ty.value).is_none() {
                 infcx.projection_cache.borrow_mut().complete_normalized(cache_key, &ty);
                 // No need to extend `obligations`.
             } else {
@@ -704,7 +704,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
 fn prune_cache_value_obligations<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
                                                  result: &NormalizedTy<'tcx>)
                                                  -> NormalizedTy<'tcx> {
-    if !infcx.any_unresolved_type_vars(&result.value) {
+    if infcx.unresolved_type_vars(&result.value).is_none() {
         return NormalizedTy { value: result.value, obligations: vec![] };
     }
 
@@ -722,7 +722,7 @@ fn prune_cache_value_obligations<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx,
                   // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
                   // ?0>`).
                   ty::Predicate::Projection(ref data) =>
-                      infcx.any_unresolved_type_vars(&data.ty()),
+                      infcx.unresolved_type_vars(&data.ty()).is_some(),
 
                   // We are only interested in `T: Foo<X = U>` predicates, whre
                   // `U` references one of `unresolved_type_vars`. =)
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index c079a526842..495b099601d 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2507,16 +2507,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             ty::Closure(def_id, substs) => {
-                let trait_id = obligation.predicate.def_id();
-                let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait();
-                let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait();
-                if is_copy_trait || is_clone_trait {
-                    Where(ty::Binder::bind(
-                        substs.upvar_tys(def_id, self.tcx()).collect(),
-                    ))
-                } else {
-                    None
-                }
+                // (*) binder moved here
+                Where(ty::Binder::bind(
+                    substs.upvar_tys(def_id, self.tcx()).collect(),
+                ))
             }
 
             ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 57bc44ee30c..47c1c16f1f8 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -542,18 +542,13 @@ declare_lint! {
     "detects missing implementations of fmt::Debug"
 }
 
+#[derive(Default)]
 pub struct MissingDebugImplementations {
     impling_types: Option<HirIdSet>,
 }
 
 impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
 
-impl MissingDebugImplementations {
-    pub fn new() -> MissingDebugImplementations {
-        MissingDebugImplementations { impling_types: None }
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         if !cx.access_levels.is_reachable(item.hir_id) {
@@ -1285,6 +1280,7 @@ declare_lint! {
     "`...` range patterns are deprecated"
 }
 
+#[derive(Default)]
 pub struct EllipsisInclusiveRangePatterns {
     /// If `Some(_)`, suppress all subsequent pattern
     /// warnings for better diagnostics.
@@ -1293,14 +1289,6 @@ pub struct EllipsisInclusiveRangePatterns {
 
 impl_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);
 
-impl EllipsisInclusiveRangePatterns {
-    pub fn new() -> Self {
-        Self {
-            node_id: None,
-        }
-    }
-}
-
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) {
         if self.node_id.is_some() {
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 68ea2195619..7d23da857bb 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -94,7 +94,7 @@ macro_rules! early_lint_passes {
             UnusedImportBraces: UnusedImportBraces,
             UnsafeCode: UnsafeCode,
             AnonymousParameters: AnonymousParameters,
-            EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::new(),
+            EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
             NonCamelCaseTypes: NonCamelCaseTypes,
             DeprecatedAttr: DeprecatedAttr::new(),
         ]);
@@ -132,7 +132,7 @@ macro_rules! late_lint_passes {
             // Depends on access levels
             // FIXME: Turn the computation of types which implement Debug into a query
             // and change this to a module lint pass
-            MissingDebugImplementations: MissingDebugImplementations::new(),
+            MissingDebugImplementations: MissingDebugImplementations::default(),
         ]);
     )
 }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 7ab33411275..e54a24f4df1 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -759,6 +759,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 }
             }
         }
+        hir::ExprKind::Use(ref source) => {
+            ExprKind::Use { source: source.to_ref() }
+        }
         hir::ExprKind::Box(ref value) => {
             ExprKind::Box {
                 value: value.to_ref(),
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index e2c5c4ee374..2a423cc4166 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -436,7 +436,9 @@ fn check_expr_kind<'a, 'tcx>(
         hir::ExprKind::Err => Promotable,
 
         hir::ExprKind::AddrOf(_, ref expr) |
-        hir::ExprKind::Repeat(ref expr, _) => {
+        hir::ExprKind::Repeat(ref expr, _) |
+        hir::ExprKind::Type(ref expr, _) |
+        hir::ExprKind::Use(ref expr) => {
             v.check_expr(&expr)
         }
 
@@ -483,10 +485,6 @@ fn check_expr_kind<'a, 'tcx>(
             array_result
         }
 
-        hir::ExprKind::Type(ref expr, ref _ty) => {
-            v.check_expr(&expr)
-        }
-
         hir::ExprKind::Tup(ref hirvec) => {
             let mut tup_result = Promotable;
             for index in hirvec.iter() {
@@ -495,7 +493,6 @@ fn check_expr_kind<'a, 'tcx>(
             tup_result
         }
 
-
         // Conditional control flow (possible to implement).
         hir::ExprKind::Match(ref expr, ref hirvec_arm, ref _match_source) => {
             // Compute the most demanding borrow from all the arms'
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 5c095994a1b..7cd26dce144 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1642,6 +1642,19 @@ fn main() {
 ```
 "##,
 
+E0671: r##"
+Const parameters cannot depend on type parameters.
+The following is therefore invalid:
+```compile_fail,E0671
+#![feature(const_generics)]
+
+fn const_id<T, const N: T>() -> T { // error: const parameter
+                                    // depends on type parameter
+    N
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f6b62146c60..be68f303537 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -187,6 +187,8 @@ enum ResolutionError<'a> {
     BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
     /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
     ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
+    /// Error E0671: const parameter cannot depend on type parameter.
+    ConstParamDependentOnTypeParam,
 }
 
 /// Combines an error with provided span and emits it.
@@ -442,6 +444,16 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                 span, "defaulted type parameters cannot be forward declared".to_string());
             err
         }
+        ResolutionError::ConstParamDependentOnTypeParam => {
+            let mut err = struct_span_err!(
+                resolver.session,
+                span,
+                E0671,
+                "const parameters cannot depend on type parameters"
+            );
+            err.span_label(span, format!("const parameter depends on type parameter"));
+            err
+        }
     }
 }
 
@@ -917,6 +929,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                 }
             }));
 
+        // We also ban access to type parameters for use as the types of const parameters.
+        let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
+        const_ty_param_ban_rib.bindings.extend(generics.params.iter()
+            .filter(|param| {
+                if let GenericParamKind::Type { .. } = param.kind {
+                    true
+                } else {
+                    false
+                }
+            })
+            .map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));
+
         for param in &generics.params {
             match param.kind {
                 GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -935,11 +959,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                     default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
                 }
                 GenericParamKind::Const { ref ty } => {
+                    self.ribs[TypeNS].push(const_ty_param_ban_rib);
+
                     for bound in &param.bounds {
                         self.visit_param_bound(bound);
                     }
 
                     self.visit_ty(ty);
+
+                    const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
                 }
             }
         }
@@ -996,6 +1024,9 @@ enum RibKind<'a> {
     /// from the default of a type parameter because they're not declared
     /// before said type parameter. Also see the `visit_generics` override.
     ForwardTyParamBanRibKind,
+
+    /// We forbid the use of type parameters as the types of const parameters.
+    TyParamAsConstParamTy,
 }
 
 /// A single local scope.
@@ -3946,6 +3977,15 @@ impl<'a> Resolver<'a> {
             return Def::Err;
         }
 
+        // An invalid use of a type parameter as the type of a const parameter.
+        if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
+            if record_used {
+                resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
+            }
+            assert_eq!(def, Def::Err);
+            return Def::Err;
+        }
+
         match def {
             Def::Upvar(..) => {
                 span_bug!(span, "unexpected {:?} in bindings", def)
@@ -3957,7 +3997,7 @@ impl<'a> Resolver<'a> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
-                        ForwardTyParamBanRibKind => {
+                        ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -4015,7 +4055,7 @@ impl<'a> Resolver<'a> {
                     match rib.kind {
                         NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
                         ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
-                        ConstantItemRibKind => {
+                        ConstantItemRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind | FnItemRibKind => {
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index ae9f1a27b94..27af8511915 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -6,10 +6,42 @@ use rustc::traits::{
 };
 use rustc::ty;
 use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use crate::lowering::Lower;
 use crate::generic_types;
 
+/// Returns a predicate of the form
+/// `Implemented(ty: Trait) :- Implemented(nested: Trait)...`
+/// where `Trait` is specified by `trait_def_id`.
+fn builtin_impl_clause(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    ty: ty::Ty<'tcx>,
+    nested: &[ty::Ty<'tcx>],
+    trait_def_id: DefId
+) -> ProgramClause<'tcx> {
+    ProgramClause {
+        goal: ty::TraitPredicate {
+            trait_ref: ty::TraitRef {
+                def_id: trait_def_id,
+                substs: tcx.mk_substs_trait(ty, &[]),
+            },
+        }.lower(),
+        hypotheses: tcx.mk_goals(
+            nested.iter()
+                .cloned()
+                .map(|nested_ty| ty::TraitRef {
+                    def_id: trait_def_id,
+                    substs: tcx.mk_substs_trait(nested_ty, &[]),
+                })
+                .map(|trait_ref| ty::TraitPredicate { trait_ref })
+                .map(|pred| GoalKind::DomainGoal(pred.lower()))
+                .map(|goal_kind| tcx.mk_goal(goal_kind))
+        ),
+        category: ProgramClauseCategory::Other,
+    }
+}
+
 crate fn assemble_builtin_unsize_impls<'tcx>(
     tcx: ty::TyCtxt<'_, '_, 'tcx>,
     unsize_def_id: DefId,
@@ -93,26 +125,7 @@ crate fn assemble_builtin_sized_impls<'tcx>(
     clauses: &mut Vec<Clause<'tcx>>
 ) {
     let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
-        let clause = ProgramClause {
-            goal: ty::TraitPredicate {
-                trait_ref: ty::TraitRef {
-                    def_id: sized_def_id,
-                    substs: tcx.mk_substs_trait(ty, &[]),
-                },
-            }.lower(),
-            hypotheses: tcx.mk_goals(
-                nested.iter()
-                    .cloned()
-                    .map(|nested_ty| ty::TraitRef {
-                        def_id: sized_def_id,
-                        substs: tcx.mk_substs_trait(nested_ty, &[]),
-                    })
-                    .map(|trait_ref| ty::TraitPredicate { trait_ref })
-                    .map(|pred| GoalKind::DomainGoal(pred.lower()))
-                    .map(|goal_kind| tcx.mk_goal(goal_kind))
-            ),
-            category: ProgramClauseCategory::Other,
-        };
+        let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id);
         // Bind innermost bound vars that may exist in `ty` and `nested`.
         clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
     };
@@ -124,6 +137,8 @@ crate fn assemble_builtin_sized_impls<'tcx>(
         ty::Int(..) |
         ty::Uint(..) |
         ty::Float(..) |
+        ty::Infer(ty::IntVar(_)) |
+        ty::Infer(ty::FloatVar(_)) |
         ty::Error |
         ty::Never => push_builtin_impl(ty, &[]),
 
@@ -175,14 +190,11 @@ crate fn assemble_builtin_sized_impls<'tcx>(
             push_builtin_impl(adt, &sized_constraint);
         }
 
-        // Artificially trigger an ambiguity.
-        ty::Infer(..) => {
-            // Everybody can find at least two types to unify against:
-            // general ty vars, int vars and float vars.
+        // Artificially trigger an ambiguity by adding two possible types to
+        // unify against.
+        ty::Infer(ty::TyVar(_)) => {
             push_builtin_impl(tcx.types.i32, &[]);
-            push_builtin_impl(tcx.types.u32, &[]);
             push_builtin_impl(tcx.types.f32, &[]);
-            push_builtin_impl(tcx.types.f64, &[]);
         }
 
         ty::Projection(_projection_ty) => {
@@ -203,6 +215,108 @@ crate fn assemble_builtin_sized_impls<'tcx>(
         ty::Opaque(..) => (),
 
         ty::Bound(..) |
-        ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
+        ty::GeneratorWitness(..) |
+        ty::Infer(ty::FreshTy(_)) |
+        ty::Infer(ty::FreshIntTy(_)) |
+        ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
+    }
+}
+
+crate fn assemble_builtin_copy_clone_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    trait_def_id: DefId,
+    ty: ty::Ty<'tcx>,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
+        let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id);
+        // Bind innermost bound vars that may exist in `ty` and `nested`.
+        clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+    };
+
+    match &ty.sty {
+        // Implementations provided in libcore.
+        ty::Bool |
+        ty::Char |
+        ty::Int(..) |
+        ty::Uint(..) |
+        ty::Float(..) |
+        ty::RawPtr(..) |
+        ty::Never |
+        ty::Ref(_, _, hir::MutImmutable) => (),
+
+        // Non parametric primitive types.
+        ty::Infer(ty::IntVar(_)) |
+        ty::Infer(ty::FloatVar(_)) |
+        ty::Error => push_builtin_impl(ty, &[]),
+
+        // These implement `Copy`/`Clone` if their element types do.
+        &ty::Array(_, length) => {
+            let element_ty = generic_types::bound(tcx, 0);
+            push_builtin_impl(tcx.mk_ty(ty::Array(element_ty, length)), &[element_ty]);
+        }
+        &ty::Tuple(type_list) => {
+            let type_list = generic_types::type_list(tcx, type_list.len());
+            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
+        }
+        &ty::Closure(def_id, ..) => {
+            let closure_ty = generic_types::closure(tcx, def_id);
+            let upvar_tys: Vec<_> = match &closure_ty.sty {
+                ty::Closure(_, substs) => substs.upvar_tys(def_id, tcx).collect(),
+                _ => bug!(),
+            };
+            push_builtin_impl(closure_ty, &upvar_tys);
+        }
+
+        // These ones are always `Clone`.
+        ty::FnPtr(fn_ptr) => {
+            let fn_ptr = fn_ptr.skip_binder();
+            let fn_ptr = generic_types::fn_ptr(
+                tcx,
+                fn_ptr.inputs_and_output.len(),
+                fn_ptr.c_variadic,
+                fn_ptr.unsafety,
+                fn_ptr.abi
+            );
+            push_builtin_impl(fn_ptr, &[]);
+        }
+        &ty::FnDef(def_id, ..) => {
+            push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
+        }
+
+        // These depend on whatever user-defined impls might exist.
+        ty::Adt(_, _) => (),
+
+        // Artificially trigger an ambiguity by adding two possible types to
+        // unify against.
+        ty::Infer(ty::TyVar(_)) => {
+            push_builtin_impl(tcx.types.i32, &[]);
+            push_builtin_impl(tcx.types.f32, &[]);
+        }
+
+        ty::Projection(_projection_ty) => {
+            // FIXME: add builtin impls from the associated type values found in
+            // trait impls of `projection_ty.trait_ref(tcx)`.
+        }
+
+        // The `Copy`/`Clone` bound can only come from the environment.
+        ty::Param(..) |
+        ty::Placeholder(..) |
+        ty::UnnormalizedProjection(..) |
+        ty::Opaque(..) => (),
+
+        // Definitely not `Copy`/`Clone`.
+        ty::Dynamic(..) |
+        ty::Foreign(..) |
+        ty::Generator(..) |
+        ty::Str |
+        ty::Slice(..) |
+        ty::Ref(_, _, hir::MutMutable) => (),
+
+        ty::Bound(..) |
+        ty::GeneratorWitness(..) |
+        ty::Infer(ty::FreshTy(_)) |
+        ty::Infer(ty::FreshIntTy(_)) |
+        ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty),
     }
 }
diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs
index 80fbd97c587..7feb63bb100 100644
--- a/src/librustc_traits/chalk_context/program_clauses/mod.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/mod.rs
@@ -96,8 +96,27 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
                     );
                 }
 
+                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() {
+                    assemble_builtin_copy_clone_impls(
+                        self.infcx.tcx,
+                        trait_predicate.def_id(),
+                        trait_predicate.self_ty(),
+                        &mut clauses
+                    );
+                }
+
+                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() {
+                    // For all builtin impls, the conditions for `Copy` and
+                    // `Clone` are the same.
+                    assemble_builtin_copy_clone_impls(
+                        self.infcx.tcx,
+                        trait_predicate.def_id(),
+                        trait_predicate.self_ty(),
+                        &mut clauses
+                    );
+                }
+
                 // FIXME: we need to add special rules for other builtin impls:
-                // * `Copy` / `Clone`
                 // * `Generator`
                 // * `FnOnce` / `FnMut` / `Fn`
                 // * trait objects
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index 7f4b0a96a15..0866c57616e 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -54,12 +54,16 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
             debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
                    expr, scope, ty, self.expr_count, yield_span);
 
-            if self.fcx.any_unresolved_type_vars(&ty) {
-                let mut err = struct_span_err!(self.fcx.tcx.sess, source_span, E0698,
-                    "type inside generator must be known in this context");
-                err.span_note(yield_span,
-                              "the type is part of the generator because of this `yield`");
-                err.emit();
+            if let Some((unresolved_type, unresolved_type_span)) =
+                self.fcx.unresolved_type_vars(&ty)
+            {
+                // If unresolved type isn't a ty_var then unresolved_type_span is None
+                self.fcx.need_type_info_err_in_generator(
+                    unresolved_type_span.unwrap_or(yield_span),
+                    unresolved_type)
+                    .span_note(yield_span,
+                               "the type is part of the generator because of this `yield`")
+                    .emit();
             } else {
                 // Map the type to the number of types added before it
                 let entries = self.types.len();
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 9f0c377e19c..d2d05982c61 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4535,6 +4535,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.check_expr_eq_type(&e, ty);
                 ty
             }
+            ExprKind::Use(ref e) => {
+                self.check_expr_with_expectation(e, expected)
+            }
             ExprKind::Array(ref args) => {
                 let uty = expected.to_option(self).and_then(|uty| {
                     match uty.sty {
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 78ce0bf9cc1..d1ca0578093 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -443,13 +443,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     ) -> bool /* did we suggest to call a function because of missing parenthesis? */ {
         err.span_label(span, ty.to_string());
         if let FnDef(def_id, _) = ty.sty {
+            let source_map = self.tcx.sess.source_map();
+            let hir_id = match self.tcx.hir().as_local_hir_id(def_id) {
+                Some(hir_id) => hir_id,
+                None => return false,
+            };
             if self.tcx.has_typeck_tables(def_id) == false {
                 return false;
             }
-            let source_map = self.tcx.sess.source_map();
-            let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap();
             let fn_sig = {
-                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) {
+                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(hir_id) {
                     Some(f) => f.clone(),
                     None => {
                         bug!("No fn-sig entry for def_id={:?}", def_id);
@@ -458,11 +461,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             };
 
             let other_ty = if let FnDef(def_id, _) = other_ty.sty {
+                let hir_id = match self.tcx.hir().as_local_hir_id(def_id) {
+                    Some(hir_id) => hir_id,
+                    None => return false,
+                };
                 if self.tcx.has_typeck_tables(def_id) == false {
                     return false;
                 }
-                let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap();
-                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) {
+                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(hir_id) {
                     Some(f) => f.clone().output(),
                     None => {
                         bug!("No fn-sig entry for def_id={:?}", def_id);
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index dc23a92adbb..ba67593ce96 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -4730,7 +4730,6 @@ register_diagnostics! {
     E0640, // infer outlives requirements
     E0641, // cannot cast to/from a pointer with an unknown kind
     E0645, // trait aliases not finished
-    E0698, // type inside generator must be known in this context
     E0719, // duplicate values for associated type binding
     E0722, // Malformed #[optimize] attribute
     E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 4941867d8df..6cedab412df 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -10,6 +10,6 @@ path = "lib.rs"
 
 [dependencies]
 pulldown-cmark = { version = "0.4.1", default-features = false }
-minifier = "0.0.29"
+minifier = "0.0.30"
 tempfile = "3"
 parking_lot = "0.7"
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 769ea3ff7bc..72421c9decc 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -351,6 +351,9 @@ impl Options {
                             .unwrap_or_else(|| PathBuf::from("doc"));
         let mut cfgs = matches.opt_strs("cfg");
         cfgs.push("rustdoc".to_string());
+        if should_test {
+            cfgs.push("test".to_string());
+        }
 
         let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 2c4e1cde880..0a0a9ff64b9 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -953,40 +953,15 @@ themePicker.onblur = handleThemeButtonsBlur;
         key: &str,
         for_search_index: bool,
     ) -> io::Result<(Vec<String>, Vec<String>, Vec<String>)> {
-        use minifier::js;
-
         let mut ret = Vec::new();
         let mut krates = Vec::new();
         let mut variables = Vec::new();
 
-        let mut krate = krate.to_owned();
-
         if path.exists() {
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
                 if for_search_index && line.starts_with("var R") {
                     variables.push(line.clone());
-                    // We need to check if the crate name has been put into a variable as well.
-                    let tokens: js::Tokens<'_> = js::simple_minify(&line)
-                                                    .into_iter()
-                                                    .filter(js::clean_token)
-                                                    .collect::<Vec<_>>()
-                                                    .into();
-                    let mut pos = 0;
-                    while pos < tokens.len() {
-                        if let Some((var_pos, Some(value_pos))) =
-                                js::get_variable_name_and_value_positions(&tokens, pos) {
-                            if let Some(s) = tokens.0[value_pos].get_string() {
-                                if &s[1..s.len() - 1] == krate {
-                                    if let Some(var) = tokens[var_pos].get_other() {
-                                        krate = var.to_owned();
-                                        break
-                                    }
-                                }
-                            }
-                        }
-                        pos += 1;
-                    }
                     continue;
                 }
                 if !line.starts_with(key) {
@@ -1342,10 +1317,20 @@ fn write_minify_replacer<W: Write>(
                         .into();
                     tokens.apply(|f| {
                         // We add a backline after the newly created variables.
-                        minifier::js::aggregate_strings_into_array_with_separation(
+                        minifier::js::aggregate_strings_into_array_with_separation_filter(
                             f,
                             "R",
                             Token::Char(ReservedChar::Backline),
+                            // This closure prevents crates' names from being aggregated.
+                            //
+                            // The point here is to check if the string is preceded by '[' and
+                            // "searchIndex". If so, it means this is a crate name and that it
+                            // shouldn't be aggregated.
+                            |tokens, pos| {
+                                pos < 2 ||
+                                !tokens[pos - 1].is_char(ReservedChar::OpenBracket) ||
+                                tokens[pos - 2].get_other() != Some("searchIndex")
+                            }
                         )
                     })
                     .to_string()
@@ -1360,7 +1345,8 @@ fn write_minify_replacer<W: Write>(
 /// static HTML tree. Each component in the cleaned path will be passed as an
 /// argument to `f`. The very last component of the path (ie the file name) will
 /// be passed to `f` if `keep_filename` is true, and ignored otherwise.
-fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where
+fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F)
+where
     F: FnMut(&OsStr),
 {
     // make it relative, if possible
@@ -1472,11 +1458,11 @@ impl<'a> SourceCollector<'a> {
         let mut href = String::new();
         clean_srcpath(&self.scx.src_root, &p, false, |component| {
             cur.push(component);
-            fs::create_dir_all(&cur).unwrap();
             root_path.push_str("../");
             href.push_str(&component.to_string_lossy());
             href.push('/');
         });
+        fs::create_dir_all(&cur)?;
         let mut fname = p.file_name()
                          .expect("source has no filename")
                          .to_os_string();
@@ -1485,7 +1471,7 @@ impl<'a> SourceCollector<'a> {
         href.push_str(&fname.to_string_lossy());
 
         let mut w = BufWriter::new(File::create(&cur)?);
-        let title = format!("{} -- source", cur.file_name().unwrap()
+        let title = format!("{} -- source", cur.file_name().expect("failed to get file name")
                                                .to_string_lossy());
         let desc = format!("Source to the Rust file `{}`.", filename);
         let page = layout::Page {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ba567a123ae..98952ad918c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -403,6 +403,7 @@ declare_features! (
     (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
     (active, movbe_target_feature, "1.34.0", Some(44839), None),
     (active, rtm_target_feature, "1.35.0", Some(44839), None),
+    (active, f16c_target_feature, "1.36.0", Some(44839), None),
 
     // Allows macro invocations on modules expressions and statements and
     // procedural macros to expand to non-items.
@@ -2258,32 +2259,32 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                 continue;
             }
 
-            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
-                if let Some(allowed) = allow_features.as_ref() {
-                    if allowed.iter().find(|f| *f == name.as_str()).is_none() {
-                        span_err!(span_handler, mi.span(), E0725,
-                                  "the feature `{}` is not in the list of allowed features",
-                                  name);
-                        continue;
-                    }
-                }
-
-                set(&mut features, mi.span());
-                features.declared_lang_features.push((name, mi.span(), None));
-                continue
-            }
-
             let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
             let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
             if let Some((.., reason)) = removed.or(stable_removed) {
                 feature_removed(span_handler, mi.span(), *reason);
-                continue
+                continue;
             }
 
             if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
                 let since = Some(Symbol::intern(since));
                 features.declared_lang_features.push((name, mi.span(), since));
-                continue
+                continue;
+            }
+
+            if let Some(allowed) = allow_features.as_ref() {
+                if allowed.iter().find(|f| *f == name.as_str()).is_none() {
+                    span_err!(span_handler, mi.span(), E0725,
+                              "the feature `{}` is not in the list of allowed features",
+                              name);
+                    continue;
+                }
+            }
+
+            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
+                set(&mut features, mi.span());
+                features.declared_lang_features.push((name, mi.span(), None));
+                continue;
             }
 
             features.declared_lib_features.push((name, mi.span()));
diff --git a/src/test/run-pass/chalkify/builtin-copy-clone.rs b/src/test/run-pass/chalkify/builtin-copy-clone.rs
new file mode 100644
index 00000000000..4f69714bc74
--- /dev/null
+++ b/src/test/run-pass/chalkify/builtin-copy-clone.rs
@@ -0,0 +1,43 @@
+// compile-flags: -Z chalk
+
+// Test that `Clone` is correctly implemented for builtin types.
+
+#[derive(Copy, Clone)]
+struct S(i32);
+
+fn test_clone<T: Clone>(arg: T) {
+    let _ = arg.clone();
+}
+
+fn test_copy<T: Copy>(arg: T) {
+    let _ = arg;
+    let _ = arg;
+}
+
+fn test_copy_clone<T: Copy + Clone>(arg: T) {
+    test_copy(arg);
+    test_clone(arg);
+}
+
+fn foo() { }
+
+fn main() {
+    test_copy_clone(foo);
+    let f: fn() = foo;
+    test_copy_clone(f);
+    // FIXME: add closures when they're considered WF
+    test_copy_clone([1; 56]);
+    test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
+    test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1));
+    test_copy_clone(());
+    test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ()));
+
+    let a = (
+        (S(1), S(0)),
+        (
+            (S(0), S(0), S(1)),
+            S(0)
+        )
+    );
+    test_copy_clone(a);
+}
diff --git a/src/test/rustdoc-ui/cfg-test.rs b/src/test/rustdoc-ui/cfg-test.rs
new file mode 100644
index 00000000000..e26034371f4
--- /dev/null
+++ b/src/test/rustdoc-ui/cfg-test.rs
@@ -0,0 +1,19 @@
+// compile-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+
+/// this doctest will be ignored:
+///
+/// ```
+/// assert!(false);
+/// ```
+#[cfg(not(test))]
+pub struct Foo;
+
+/// this doctest will be tested:
+///
+/// ```
+/// assert!(true);
+/// ```
+#[cfg(test)]
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout
new file mode 100644
index 00000000000..30bb0038d1b
--- /dev/null
+++ b/src/test/rustdoc-ui/cfg-test.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/cfg-test.rs - Foo (line 15) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
diff --git a/src/test/rustdoc/index-page.rs b/src/test/rustdoc/index-page.rs
index 6998e735297..f0476f083b8 100644
--- a/src/test/rustdoc/index-page.rs
+++ b/src/test/rustdoc/index-page.rs
@@ -1,3 +1,5 @@
+// aux-build:all-item-types.rs
+// build-aux-docs
 // compile-flags: -Z unstable-options --enable-index-page
 
 #![crate_name = "foo"]
@@ -5,4 +7,5 @@
 // @has foo/../index.html
 // @has - '//span[@class="in-band"]' 'List of all crates'
 // @has - '//ul[@class="mod"]//a[@href="foo/index.html"]' 'foo'
+// @has - '//ul[@class="mod"]//a[@href="all_item_types/index.html"]' 'all_item_types'
 pub struct Foo;
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
new file mode 100644
index 00000000000..af5e8f49754
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
@@ -0,0 +1,6 @@
+use std::marker::PhantomData;
+
+struct B<T, const N: T>(PhantomData<[T; N]>); //~ ERROR const generics are unstable
+//~^ ERROR const parameters cannot depend on type parameters
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
new file mode 100644
index 00000000000..e3adbcfe602
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -0,0 +1,19 @@
+error[E0671]: const parameters cannot depend on type parameters
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
+   |
+LL | struct B<T, const N: T>(PhantomData<[T; N]>);
+   |                      ^ const parameter depends on type parameter
+
+error[E0658]: const generics are unstable
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
+   |
+LL | struct B<T, const N: T>(PhantomData<[T; N]>);
+   |                   ^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
+   = help: add #![feature(const_generics)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0658, E0671.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
new file mode 100644
index 00000000000..28e0d6c2bb7
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
@@ -0,0 +1,13 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+// Currently, const parameters cannot depend on type parameters, because there is no way to
+// enforce the `structural_match` property on an arbitrary type parameter. This restriction
+// may be relaxed in the future. See https://github.com/rust-lang/rfcs/pull/2000 for more
+// details.
+
+pub struct Dependent<T, const X: T>([(); X]);
+//~^ ERROR const parameters cannot depend on type parameters
+//~^^ ERROR parameter `T` is never used
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
new file mode 100644
index 00000000000..c7dcbe13542
--- /dev/null
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
@@ -0,0 +1,24 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-type-depends-on-type-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0671]: const parameters cannot depend on type parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                                  ^ const parameter depends on type parameter
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:9:22
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                      ^ unused parameter
+   |
+   = help: consider removing `T` or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0392, E0671.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/feature-gate/allow-features-empty.rs b/src/test/ui/feature-gate/allow-features-empty.rs
index 83250052cb5..784a1d2697d 100644
--- a/src/test/ui/feature-gate/allow-features-empty.rs
+++ b/src/test/ui/feature-gate/allow-features-empty.rs
@@ -7,4 +7,6 @@
 
 #![feature(lang_items)] //~ ERROR
 
+#![feature(unknown_stdlib_feature)] //~ ERROR
+
 fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features-empty.stderr b/src/test/ui/feature-gate/allow-features-empty.stderr
index cce2c4078c2..ab41422ed05 100644
--- a/src/test/ui/feature-gate/allow-features-empty.stderr
+++ b/src/test/ui/feature-gate/allow-features-empty.stderr
@@ -16,6 +16,12 @@ error[E0725]: the feature `lang_items` is not in the list of allowed features
 LL | #![feature(lang_items)]
    |            ^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features
+  --> $DIR/allow-features-empty.rs:10:12
+   |
+LL | #![feature(unknown_stdlib_feature)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/feature-gate/allow-features.rs b/src/test/ui/feature-gate/allow-features.rs
index 1cebc8f34f2..de3439a5b62 100644
--- a/src/test/ui/feature-gate/allow-features.rs
+++ b/src/test/ui/feature-gate/allow-features.rs
@@ -7,4 +7,6 @@
 
 #![feature(lang_items)]
 
+#![feature(unknown_stdlib_feature)] //~ ERROR
+
 fn main() {}
diff --git a/src/test/ui/feature-gate/allow-features.stderr b/src/test/ui/feature-gate/allow-features.stderr
index b13560fb81c..5b39a6f053b 100644
--- a/src/test/ui/feature-gate/allow-features.stderr
+++ b/src/test/ui/feature-gate/allow-features.stderr
@@ -4,6 +4,12 @@ error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed f
 LL | #![feature(rustc_const_unstable)]
    |            ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features
+  --> $DIR/allow-features.rs:10:12
+   |
+LL | #![feature(unknown_stdlib_feature)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0725`.
diff --git a/src/test/ui/generator/unresolved_type_param.rs b/src/test/ui/generator/unresolved_type_param.rs
new file mode 100644
index 00000000000..f49369b125f
--- /dev/null
+++ b/src/test/ui/generator/unresolved_type_param.rs
@@ -0,0 +1,14 @@
+// Provoke an unresolved type error (T).
+// Error message should pinpoint the type parameter T as needing to be bound
+// (rather than give a general error message)
+// edition:2018
+#![feature(futures_api, async_await, await_macro)]
+async fn bar<T>() -> () {}
+
+async fn foo() {
+        await!(bar());
+        //~^ ERROR type inside generator must be known in this context
+        //~| NOTE cannot infer type for `T`
+        //~| NOTE the type is part of the generator because of this `yield`
+}
+fn main() {}
diff --git a/src/test/ui/generator/unresolved_type_param.stderr b/src/test/ui/generator/unresolved_type_param.stderr
new file mode 100644
index 00000000000..57ccdda3f43
--- /dev/null
+++ b/src/test/ui/generator/unresolved_type_param.stderr
@@ -0,0 +1,16 @@
+error[E0698]: type inside generator must be known in this context
+  --> $DIR/unresolved_type_param.rs:9:16
+   |
+LL |         await!(bar());
+   |                ^^^ cannot infer type for `T`
+   |
+note: the type is part of the generator because of this `yield`
+  --> $DIR/unresolved_type_param.rs:9:9
+   |
+LL |         await!(bar());
+   |         ^^^^^^^^^^^^^^
+   = 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
+
+For more information about this error, try `rustc --explain E0698`.
diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs
index 8f3a52ba5d6..bc7f7caa107 100644
--- a/src/test/ui/target-feature-gate.rs
+++ b/src/test/ui/target-feature-gate.rs
@@ -24,6 +24,7 @@
 // gate-test-cmpxchg16b_target_feature
 // gate-test-movbe_target_feature
 // gate-test-rtm_target_feature
+// gate-test-f16c_target_feature
 // min-llvm-version 6.0
 
 #[target_feature(enable = "avx512bw")]
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
index e142125225f..c7adba868ea 100644
--- a/src/test/ui/target-feature-gate.stderr
+++ b/src/test/ui/target-feature-gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/target-feature-gate.rs:29:18
+  --> $DIR/target-feature-gate.rs:30:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^