diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index b38fd804ee80f..73e760a2ee8b3 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -474,11 +474,11 @@ impl f64 {
     /// assuming that the value is finite and fits in that type.
     ///
     /// ```
-    /// let value = 4.6_f32;
+    /// let value = 4.6_f64;
     /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
     /// assert_eq!(rounded, 4);
     ///
-    /// let value = -128.9_f32;
+    /// let value = -128.9_f64;
     /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
     /// assert_eq!(rounded, i8::MIN);
     /// ```
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index fa5993471c44a..aca1c69dfd591 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -255,8 +255,8 @@ fn generate_test_harness(
 ///
 /// The expansion here can be controlled by two attributes:
 ///
-/// `reexport_test_harness_main` provides a different name for the `main`
-/// function and `test_runner` provides a path that replaces
+/// [`TestCtxt::reexport_test_harness_main`] provides a different name for the `main`
+/// function and [`TestCtxt::test_runner`] provides a path that replaces
 /// `test::test_main_static`.
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let sp = cx.def_site;
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 4033c2b28494c..521a0d67b59da 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -6,9 +6,9 @@
 //! other phases of the compiler, which are generally required to hold in order
 //! to compile the program at all.
 //!
-//! Most lints can be written as `LintPass` instances. These run after
+//! Most lints can be written as [LintPass] instances. These run after
 //! all other analyses. The `LintPass`es built into rustc are defined
-//! within `rustc_session::lint::builtin`,
+//! within [rustc_session::lint::builtin],
 //! which has further comments on how to add such a lint.
 //! rustc can also load user-defined lint plugins via the plugin mechanism.
 //!
@@ -19,7 +19,7 @@
 //! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
 //! in `context.rs`.
 //!
-//! Some code also exists in `rustc_session::lint`, `rustc_middle::lint`.
+//! Some code also exists in [rustc_session::lint], [rustc_middle::lint].
 //!
 //! ## Note
 //!
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index aae80185b4d6e..7926bf535b3b7 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -787,6 +787,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
             | NonMutatingUse(NonMutatingUseContext::Inspect)
             | NonMutatingUse(NonMutatingUseContext::Projection)
             | NonUse(_) => {}
+            // FIXME(felix91gr): explain the reasoning behind this
             MutatingUse(MutatingUseContext::Projection) => {
                 if self.local_kinds[local] != LocalKind::Temp {
                     self.can_const_prop[local] = ConstPropMode::NoPropagation;
@@ -969,13 +970,58 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::FalseEdges { .. }
             | TerminatorKind::FalseUnwind { .. } => {}
-            //FIXME(wesleywiser) Call does have Operands that could be const-propagated
-            TerminatorKind::Call { .. } => {}
+            // Every argument in our function calls can be const propagated.
+            TerminatorKind::Call { ref mut args, .. } => {
+                let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
+                // Constant Propagation into function call arguments is gated
+                // under mir-opt-level 2, because LLVM codegen gives performance
+                // regressions with it.
+                if mir_opt_level >= 2 {
+                    for opr in args {
+                        /*
+                          The following code would appear to be incomplete, because
+                          the function `Operand::place()` returns `None` if the
+                          `Operand` is of the variant `Operand::Constant`. In this
+                          context however, that variant will never appear. This is why:
+
+                          When constructing the MIR, all function call arguments are
+                          copied into `Locals` of `LocalKind::Temp`. At least, all arguments
+                          that are not unsized (Less than 0.1% are unsized. See #71170
+                          to learn more about those).
+
+                          This means that, conversely, all `Operands` found as function call
+                          arguments are of the variant `Operand::Copy`. This allows us to
+                          simplify our handling of `Operands` in this case.
+                        */
+                        if let Some(l) = opr.place().and_then(|p| p.as_local()) {
+                            if let Some(value) = self.get_const(l) {
+                                if self.should_const_prop(value) {
+                                    // FIXME(felix91gr): this code only handles `Scalar` cases.
+                                    // For now, we're not handling `ScalarPair` cases because
+                                    // doing so here would require a lot of code duplication.
+                                    // We should hopefully generalize `Operand` handling into a fn,
+                                    // and use it to do const-prop here and everywhere else
+                                    // where it makes sense.
+                                    if let interpret::Operand::Immediate(
+                                        interpret::Immediate::Scalar(
+                                            interpret::ScalarMaybeUndef::Scalar(scalar),
+                                        ),
+                                    ) = *value
+                                    {
+                                        *opr = self.operand_from_scalar(
+                                            scalar,
+                                            value.layout.ty,
+                                            source_info.span,
+                                        );
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
         }
         // We remove all Locals which are restricted in propagation to their containing blocks.
-        // We wouldn't need to clone, but the borrow checker can't see that we're not aliasing
-        // the locals_of_current_block field, so we need to clone it first.
-        // let ecx = &mut self.ecx;
         for local in self.locals_of_current_block.iter() {
             Self::remove_const(&mut self.ecx, local);
         }
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index ad87afc3e0301..4cc6a27a6da93 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -111,21 +111,22 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
             }
 
             if let Some(non_sm_ty) = structural {
-                let adt_def = match non_sm_ty {
-                    traits::NonStructuralMatchTy::Adt(adt_def) => adt_def,
+                let msg = match non_sm_ty {
+                    traits::NonStructuralMatchTy::Adt(adt_def) => {
+                        let path = self.tcx().def_path_str(adt_def.did);
+                        format!(
+                            "to use a constant of type `{}` in a pattern, \
+                             `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                            path, path,
+                        )
+                    }
+                    traits::NonStructuralMatchTy::Dynamic => {
+                        format!("trait objects cannot be used in patterns")
+                    }
                     traits::NonStructuralMatchTy::Param => {
                         bug!("use of constant whose type is a parameter inside a pattern")
                     }
                 };
-                let path = self.tcx().def_path_str(adt_def.did);
-
-                let make_msg = || -> String {
-                    format!(
-                        "to use a constant of type `{}` in a pattern, \
-                         `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                        path, path,
-                    )
-                };
 
                 // double-check there even *is* a semantic `PartialEq` to dispatch to.
                 //
@@ -155,13 +156,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
 
                 if !ty_is_partial_eq {
                     // span_fatal avoids ICE from resolution of non-existent method (rare case).
-                    self.tcx().sess.span_fatal(self.span, &make_msg());
+                    self.tcx().sess.span_fatal(self.span, &msg);
                 } else if mir_structural_match_violation {
                     self.tcx().struct_span_lint_hir(
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         self.id,
                         self.span,
-                        |lint| lint.build(&make_msg()).emit(),
+                        |lint| lint.build(&msg).emit(),
                     );
                 } else {
                     debug!(
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index fbe1fcb08f2ef..8007290f35d85 100644
--- a/src/librustc_trait_selection/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
@@ -11,6 +11,7 @@ use rustc_span::Span;
 pub enum NonStructuralMatchTy<'tcx> {
     Adt(&'tcx AdtDef),
     Param,
+    Dynamic,
 }
 
 /// This method traverses the structure of `ty`, trying to find an
@@ -137,6 +138,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 self.found = Some(NonStructuralMatchTy::Param);
                 return true; // Stop visiting.
             }
+            ty::Dynamic(..) => {
+                self.found = Some(NonStructuralMatchTy::Dynamic);
+                return true; // Stop visiting.
+            }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
                 // `*const _`/`*mut _`, so skip `super_visit_with`.
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index cac9113fd5d30..23004cf364725 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Err(()) => {
                 // error types are considered "builtin"
-                if !lhs_ty.references_error() {
+                if !lhs_ty.references_error() && !rhs_ty.references_error() {
                     let source_map = self.tcx.sess.source_map();
                     match is_assign {
                         IsAssign::Yes => {
diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff
index 0183ff7716cbb..596ddcb43533b 100644
--- a/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff
@@ -22,20 +22,27 @@
           StorageLive(_2);                 // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
           StorageLive(_3);                 // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
 -         _3 = _1;                         // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
+-         _2 = const consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
 +         _3 = const 1u32;                 // scope 1 at $DIR/scalar_literal_propagation.rs:4:13: 4:14
-+                                          // ty::Const
+                                           // ty::Const
 +                                          // + ty: u32
 +                                          // + val: Value(Scalar(0x00000001))
 +                                          // mir::Constant
 +                                          // + span: $DIR/scalar_literal_propagation.rs:4:13: 4:14
 +                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
-          _2 = const consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
-                                           // ty::Const
++         _2 = const consume(const 1u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:4:5: 4:15
++                                          // ty::Const
                                            // + ty: fn(u32) {consume}
                                            // + val: Value(Scalar(<ZST>))
                                            // mir::Constant
                                            // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
                                            // + literal: Const { ty: fn(u32) {consume}, val: Value(Scalar(<ZST>)) }
++                                          // ty::Const
++                                          // + ty: u32
++                                          // + val: Value(Scalar(0x00000001))
++                                          // mir::Constant
++                                          // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:15
++                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff
index 0742f655730c5..0bd4ba97b3ca0 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff
@@ -50,6 +50,7 @@
 -         StorageDead(_2);                 // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28
 -         StorageDead(_1);                 // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:28: 13:29
 -         StorageLive(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
+-         StorageLive(_5);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21
 -         StorageLive(_6);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16
 -         _6 = const ();                   // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16
 -                                          // ty::Const
@@ -66,6 +67,13 @@
 -                                          // mir::Constant
 -                                          // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20
 -                                          // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+-         _5 = const ((), ());             // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21
+-                                          // ty::Const
+-                                          // + ty: ((), ())
+-                                          // + val: Value(Scalar(<ZST>))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21
+-                                          // + literal: Const { ty: ((), ()), val: Value(Scalar(<ZST>)) }
 -         StorageDead(_7);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
 -         StorageDead(_6);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
 -         _4 = const use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
@@ -79,13 +87,15 @@
                                            // + ty: ((), ())
                                            // + val: Value(Scalar(<ZST>))
                                            // mir::Constant
-                                           // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21
+                                           // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
                                            // + literal: Const { ty: ((), ()), val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
+-         StorageDead(_5);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:21: 14:22
 -         StorageDead(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23
 -         StorageLive(_8);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
+-         StorageLive(_9);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34
 -         StorageLive(_10);                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30
 -         StorageLive(_11);                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28
 -         _11 = const Temp { x: 40u8 };    // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28
@@ -105,6 +115,13 @@
 -                                          // mir::Constant
 -                                          // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30
 -                                          // + literal: Const { ty: u8, val: Value(Scalar(0x28)) }
+-         _9 = const 42u8;                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34
+-                                          // ty::Const
+-                                          // + ty: u8
+-                                          // + val: Value(Scalar(0x2a))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34
+-                                          // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) }
 -         StorageDead(_10);                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:33: 16:34
 -         _8 = const use_u8(const 42u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
 -                                          // ty::Const
@@ -117,11 +134,12 @@
                                            // + ty: u8
                                            // + val: Value(Scalar(0x2a))
                                            // mir::Constant
-                                           // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34
+                                           // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
                                            // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) }
       }
   
       bb2: {
+-         StorageDead(_9);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:34: 16:35
 -         StorageDead(_11);                // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36
 -         StorageDead(_8);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36
 +         StorageDead(_2);                 // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs
new file mode 100644
index 0000000000000..2bacd6c9a9c5a
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs
@@ -0,0 +1,15 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+trait A {}
+struct B;
+impl A for B {}
+
+fn test<const T: &'static dyn A>() {
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used
+    unimplemented!()
+}
+
+fn main() {
+    test::<{ &B }>();
+}
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr
new file mode 100644
index 0000000000000..c3db6c65a8f4c
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-63322-forbid-dyn.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/issue-63322-forbid-dyn.rs:8:18
+   |
+LL | fn test<const T: &'static dyn A>() {
+   |                  ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs
new file mode 100644
index 0000000000000..08b10463d3927
--- /dev/null
+++ b/src/test/ui/issues-71798.rs
@@ -0,0 +1,7 @@
+fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+    *x //~^ ERROR the trait bound `u32: std::future::Future` is not satisfied
+}
+
+fn main() {
+    let _ = test_ref & u; //~ ERROR cannot find value `u` in this scope
+}
diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr
new file mode 100644
index 0000000000000..85da87914e768
--- /dev/null
+++ b/src/test/ui/issues-71798.stderr
@@ -0,0 +1,20 @@
+error[E0425]: cannot find value `u` in this scope
+  --> $DIR/issues-71798.rs:6:24
+   |
+LL |     let _ = test_ref & u;
+   |                        ^ not found in this scope
+
+error[E0277]: the trait bound `u32: std::future::Future` is not satisfied
+  --> $DIR/issues-71798.rs:1:25
+   |
+LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `u32`
+LL |     *x
+   |     -- this returned value is of type `u32`
+   |
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/match/issue-70972-dyn-trait.rs b/src/test/ui/match/issue-70972-dyn-trait.rs
new file mode 100644
index 0000000000000..a9b2699cafdc4
--- /dev/null
+++ b/src/test/ui/match/issue-70972-dyn-trait.rs
@@ -0,0 +1,10 @@
+const F: &'static dyn Send = &7u32;
+
+fn main() {
+    let a: &dyn Send = &7u32;
+    match a {
+        F => panic!(),
+        //~^ ERROR trait objects cannot be used in patterns
+        _ => {}
+    }
+}
diff --git a/src/test/ui/match/issue-70972-dyn-trait.stderr b/src/test/ui/match/issue-70972-dyn-trait.stderr
new file mode 100644
index 0000000000000..a4e827357de6b
--- /dev/null
+++ b/src/test/ui/match/issue-70972-dyn-trait.stderr
@@ -0,0 +1,8 @@
+error: trait objects cannot be used in patterns
+  --> $DIR/issue-70972-dyn-trait.rs:6:9
+   |
+LL |         F => panic!(),
+   |         ^
+
+error: aborting due to previous error
+