diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 871fc4fafe269..f554b51800a72 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -277,7 +277,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
 struct Canonicalizer<'cx, 'tcx> {
     infcx: Option<&'cx InferCtxt<'cx, 'tcx>>,
     tcx: TyCtxt<'tcx>,
-    variables: SmallVec<[CanonicalVarInfo; 8]>,
+    variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>,
     query_state: &'cx mut OriginalQueryValues<'tcx>,
     // Note that indices is only used once `var_values` is big enough to be
     // heap-allocated.
@@ -542,7 +542,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// or returns an existing variable if `kind` has already been
     /// seen. `kind` is expected to be an unbound variable (or
     /// potentially a free region).
-    fn canonical_var(&mut self, info: CanonicalVarInfo, kind: GenericArg<'tcx>) -> BoundVar {
+    fn canonical_var(&mut self, info: CanonicalVarInfo<'tcx>, kind: GenericArg<'tcx>) -> BoundVar {
         let Canonicalizer { variables, query_state, indices, .. } = self;
 
         let var_values = &mut query_state.var_values;
@@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// representing the region `r`; return a region referencing it.
     fn canonical_var_for_region(
         &mut self,
-        info: CanonicalVarInfo,
+        info: CanonicalVarInfo<'tcx>,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
@@ -633,7 +633,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// if `ty_var` is bound to anything; if so, canonicalize
     /// *that*. Otherwise, create a new canonical variable for
     /// `ty_var`.
-    fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
+    fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> {
         let infcx = self.infcx.expect("encountered ty-var without infcx");
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
@@ -650,7 +650,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     /// `const_var`.
     fn canonicalize_const_var(
         &mut self,
-        info: CanonicalVarInfo,
+        info: CanonicalVarInfo<'tcx>,
         const_var: &'tcx ty::Const<'tcx>,
     ) -> &'tcx ty::Const<'tcx> {
         let infcx = self.infcx.expect("encountered const-var without infcx");
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 2b8c46f1de42d..0c26639e9b0fe 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -82,7 +82,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     fn instantiate_canonical_vars(
         &self,
         span: Span,
-        variables: &List<CanonicalVarInfo>,
+        variables: &List<CanonicalVarInfo<'tcx>>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> CanonicalVarValues<'tcx> {
         let var_values: IndexVec<BoundVar, GenericArg<'tcx>> = variables
@@ -100,7 +100,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     fn instantiate_canonical_var(
         &self,
         span: Span,
-        cv_info: CanonicalVarInfo,
+        cv_info: CanonicalVarInfo<'tcx>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> GenericArg<'tcx> {
         match cv_info.kind {
@@ -154,7 +154,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 self.tcx
                     .mk_const(ty::Const {
                         val: ty::ConstKind::Placeholder(placeholder_mapped),
-                        ty: self.tcx.ty_error(), // FIXME(const_generics)
+                        ty: name.ty,
                     })
                     .into()
             }
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index e3365e8590b5e..4a5fd4b2aa5c8 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             self.tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Placeholder(ty::PlaceholderConst {
                     universe: next_universe,
-                    name: bound_var,
+                    name: ty::BoundConst { var: bound_var, ty },
                 }),
                 ty,
             })
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 1e15ae49a0c38..947b016a1fc93 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -40,7 +40,7 @@ pub struct Canonical<'tcx, V> {
     pub value: V,
 }
 
-pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>;
+pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
 
 /// A set of values corresponding to the canonical variables from some
 /// `Canonical`. You can give these values to
@@ -88,11 +88,11 @@ impl Default for OriginalQueryValues<'tcx> {
 /// a copy of the canonical value in some other inference context,
 /// with fresh inference variables replacing the canonical values.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-pub struct CanonicalVarInfo {
-    pub kind: CanonicalVarKind,
+pub struct CanonicalVarInfo<'tcx> {
+    pub kind: CanonicalVarKind<'tcx>,
 }
 
-impl CanonicalVarInfo {
+impl<'tcx> CanonicalVarInfo<'tcx> {
     pub fn universe(&self) -> ty::UniverseIndex {
         self.kind.universe()
     }
@@ -113,7 +113,7 @@ impl CanonicalVarInfo {
 /// in the type-theory sense of the term -- i.e., a "meta" type system
 /// that analyzes type-like values.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-pub enum CanonicalVarKind {
+pub enum CanonicalVarKind<'tcx> {
     /// Some kind of type inference variable.
     Ty(CanonicalTyVarKind),
 
@@ -132,10 +132,10 @@ pub enum CanonicalVarKind {
     Const(ty::UniverseIndex),
 
     /// A "placeholder" that represents "any const".
-    PlaceholderConst(ty::PlaceholderConst),
+    PlaceholderConst(ty::PlaceholderConst<'tcx>),
 }
 
-impl CanonicalVarKind {
+impl<'tcx> CanonicalVarKind<'tcx> {
     pub fn universe(self) -> ty::UniverseIndex {
         match self {
             CanonicalVarKind::Ty(kind) => match kind {
@@ -287,9 +287,11 @@ pub type QueryOutlivesConstraint<'tcx> =
     ty::Binder<ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>;
 
 CloneTypeFoldableAndLiftImpls! {
-    crate::infer::canonical::Certainty,
-    crate::infer::canonical::CanonicalVarInfo,
-    crate::infer::canonical::CanonicalVarKind,
+    for <'tcx> {
+        crate::infer::canonical::Certainty,
+        crate::infer::canonical::CanonicalVarInfo<'tcx>,
+        crate::infer::canonical::CanonicalVarKind<'tcx>,
+    }
 }
 
 CloneTypeFoldableImpls! {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index aaf6a8570437c..1def4936860f1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -278,7 +278,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> {
 impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> {
     fn decode(decoder: &mut D) -> Result<Self, D::Error> {
         let len = decoder.read_usize()?;
-        let interned: Result<Vec<CanonicalVarInfo>, _> =
+        let interned: Result<Vec<CanonicalVarInfo<'tcx>>, _> =
             (0..len).map(|_| Decodable::decode(decoder)).collect();
         Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
     }
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index ede28522000af..ca51f2a941174 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -23,7 +23,7 @@ pub enum ConstKind<'tcx> {
     Bound(ty::DebruijnIndex, ty::BoundVar),
 
     /// A placeholder const - universally quantified higher-ranked const.
-    Placeholder(ty::PlaceholderConst),
+    Placeholder(ty::PlaceholderConst<'tcx>),
 
     /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
     /// variants when the code is monomorphic enough for that.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 1c6937e685c65..3838e1b006f70 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -83,7 +83,7 @@ pub struct CtxtInterners<'tcx> {
     type_: InternedSet<'tcx, TyS<'tcx>>,
     type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
     substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
-    canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
+    canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
     region: InternedSet<'tcx, RegionKind>,
     existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
     predicate: InternedSet<'tcx, PredicateInner<'tcx>>,
@@ -1613,7 +1613,7 @@ nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
 nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
 nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
 nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
-nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
+nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
 
 // This is the impl for `&'a InternalSubsts<'a>`.
@@ -2049,7 +2049,7 @@ macro_rules! slice_interners {
 slice_interners!(
     type_list: _intern_type_list(Ty<'tcx>),
     substs: _intern_substs(GenericArg<'tcx>),
-    canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo),
+    canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
     existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
     predicates: _intern_predicates(Predicate<'tcx>),
     projs: _intern_projs(ProjectionKind),
@@ -2448,7 +2448,10 @@ impl<'tcx> TyCtxt<'tcx> {
         if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
     }
 
-    pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'tcx> {
+    pub fn intern_canonical_var_infos(
+        self,
+        ts: &[CanonicalVarInfo<'tcx>],
+    ) -> CanonicalVarInfos<'tcx> {
         if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 0042b4a3a4279..06e69a0009b1f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1580,11 +1580,9 @@ impl UniverseIndex {
     }
 }
 
-/// The "placeholder index" fully defines a placeholder region.
-/// Placeholder regions are identified by both a **universe** as well
-/// as a "bound-region" within that universe. The `bound_region` is
-/// basically a name -- distinct bound regions within the same
-/// universe are just two regions with an unknown relationship to one
+/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
+/// identified by both a universe, as well as a name residing within that universe. Distinct bound
+/// regions/types/consts within the same universe simply have an unknown relationship to one
 /// another.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub struct Placeholder<T> {
@@ -1606,7 +1604,14 @@ pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
 pub type PlaceholderType = Placeholder<BoundVar>;
 
-pub type PlaceholderConst = Placeholder<BoundVar>;
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
+pub struct BoundConst<'tcx> {
+    pub var: BoundVar,
+    pub ty: Ty<'tcx>,
+}
+
+pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>;
 
 /// A `DefId` which is potentially bundled with its corresponding generic parameter
 /// in case `did` is a const argument.
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index fa229251703a5..27d90e6613748 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -34,8 +34,8 @@ use crate::sys;
 /// attacks such as HashDoS.
 ///
 /// The hashing algorithm can be replaced on a per-`HashMap` basis using the
-/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many
-/// alternative algorithms are available on crates.io, such as the [`fnv`] crate.
+/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods.
+/// There are many alternative [hashing algorithms available on crates.io].
 ///
 /// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
 /// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
@@ -57,6 +57,7 @@ use crate::sys;
 /// The original C++ version of SwissTable can be found [here], and this
 /// [CppCon talk] gives an overview of how the algorithm works.
 ///
+/// [hashing algorithms available on crates.io]: https://crates.io/keywords/hasher
 /// [SwissTable]: https://abseil.io/blog/20180927-swisstables
 /// [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
 /// [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
@@ -154,7 +155,6 @@ use crate::sys;
 /// [`default`]: Default::default
 /// [`with_hasher`]: Self::with_hasher
 /// [`with_capacity_and_hasher`]: Self::with_capacity_and_hasher
-/// [`fnv`]: https://crates.io/crates/fnv
 ///
 /// ```
 /// use std::collections::HashMap;
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 02885f519363c..c248d57a9ddf4 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -145,6 +145,9 @@ pub struct Options {
     pub render_options: RenderOptions,
     /// Output format rendering (used only for "show-coverage" option for the moment)
     pub output_format: Option<OutputFormat>,
+    /// If this option is set to `true`, rustdoc will only run checks and not generate
+    /// documentation.
+    pub run_check: bool,
 }
 
 impl fmt::Debug for Options {
@@ -185,6 +188,7 @@ impl fmt::Debug for Options {
             .field("runtool", &self.runtool)
             .field("runtool_args", &self.runtool_args)
             .field("enable-per-target-ignores", &self.enable_per_target_ignores)
+            .field("run_check", &self.run_check)
             .finish()
     }
 }
@@ -581,6 +585,7 @@ impl Options {
         let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
         let document_private = matches.opt_present("document-private-items");
         let document_hidden = matches.opt_present("document-hidden-items");
+        let run_check = matches.opt_present("check");
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -616,6 +621,7 @@ impl Options {
             runtool_args,
             enable_per_target_ignores,
             test_builder,
+            run_check,
             render_options: RenderOptions {
                 output,
                 external_html,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 616b031814fa5..a88efba77b41c 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -423,6 +423,7 @@ fn opts() -> Vec<RustcOptGroup> {
                 "specified the rustc-like binary to use as the test builder",
             )
         }),
+        unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")),
     ]
 }
 
@@ -515,6 +516,7 @@ fn main_options(options: config::Options) -> MainResult {
     // but we can't crates the Handler ahead of time because it's not Send
     let diag_opts = (options.error_format, options.edition, options.debugging_opts.clone());
     let show_coverage = options.show_coverage;
+    let run_check = options.run_check;
 
     // First, parse the crate and extract all relevant information.
     info!("starting to run rustc");
@@ -540,6 +542,9 @@ fn main_options(options: config::Options) -> MainResult {
         // if we ran coverage, bail early, we don't need to also generate docs at this point
         // (also we didn't load in any of the useful passes)
         return Ok(());
+    } else if run_check {
+        // Since we're in "check" mode, no need to generate anything beyond this point.
+        return Ok(());
     }
 
     info!("going to format");
diff --git a/src/test/rustdoc-ui/check-fail.rs b/src/test/rustdoc-ui/check-fail.rs
new file mode 100644
index 0000000000000..291fc112c3407
--- /dev/null
+++ b/src/test/rustdoc-ui/check-fail.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Z unstable-options --check
+
+#![deny(missing_docs)]
+#![deny(rustdoc)]
+
+//! ```rust,testharness
+//~^ ERROR
+//! let x = 12;
+//! ```
+
+pub fn foo() {}
+//~^ ERROR
+//~^^ ERROR
+
+/// hello
+//~^ ERROR
+///
+/// ```rust,testharness
+/// let x = 12;
+/// ```
+pub fn bar() {}
diff --git a/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr
new file mode 100644
index 0000000000000..b4f255642da53
--- /dev/null
+++ b/src/test/rustdoc-ui/check-fail.stderr
@@ -0,0 +1,57 @@
+error: missing documentation for a function
+  --> $DIR/check-fail.rs:11:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:3:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/check-fail.rs:11:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:4:9
+   |
+LL | #![deny(rustdoc)]
+   |         ^^^^^^^
+   = note: `#[deny(missing_doc_code_examples)]` implied by `#[deny(rustdoc)]`
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-fail.rs:6:1
+   |
+LL | / //! ```rust,testharness
+LL | |
+LL | | //! let x = 12;
+LL | | //! ```
+   | |_______^
+   |
+note: the lint level is defined here
+  --> $DIR/check-fail.rs:4:9
+   |
+LL | #![deny(rustdoc)]
+   |         ^^^^^^^
+   = note: `#[deny(invalid_codeblock_attributes)]` implied by `#[deny(rustdoc)]`
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-fail.rs:15:1
+   |
+LL | / /// hello
+LL | |
+LL | | ///
+LL | | /// ```rust,testharness
+LL | | /// let x = 12;
+LL | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/rustdoc-ui/check.rs b/src/test/rustdoc-ui/check.rs
new file mode 100644
index 0000000000000..022c56214d451
--- /dev/null
+++ b/src/test/rustdoc-ui/check.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags: -Z unstable-options --check
+
+#![warn(missing_docs)]
+//~^ WARN
+//~^^ WARN
+#![warn(rustdoc)]
+
+pub fn foo() {}
+//~^ WARN
+//~^^ WARN
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
new file mode 100644
index 0000000000000..27e5a736148e1
--- /dev/null
+++ b/src/test/rustdoc-ui/check.stderr
@@ -0,0 +1,49 @@
+warning: missing documentation for the crate
+  --> $DIR/check.rs:4:1
+   |
+LL | / #![warn(missing_docs)]
+LL | |
+LL | |
+LL | | #![warn(rustdoc)]
+LL | |
+LL | | pub fn foo() {}
+   | |_______________^
+   |
+note: the lint level is defined here
+  --> $DIR/check.rs:4:9
+   |
+LL | #![warn(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+  --> $DIR/check.rs:9:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^
+
+warning: missing code example in this documentation
+  --> $DIR/check.rs:4:1
+   |
+LL | / #![warn(missing_docs)]
+LL | |
+LL | |
+LL | | #![warn(rustdoc)]
+LL | |
+LL | | pub fn foo() {}
+   | |_______________^
+   |
+note: the lint level is defined here
+  --> $DIR/check.rs:7:9
+   |
+LL | #![warn(rustdoc)]
+   |         ^^^^^^^
+   = note: `#[warn(missing_doc_code_examples)]` implied by `#[warn(rustdoc)]`
+
+warning: missing code example in this documentation
+  --> $DIR/check.rs:9:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
+
diff --git a/src/test/rustdoc/check.rs b/src/test/rustdoc/check.rs
new file mode 100644
index 0000000000000..1fb4b35ddbe86
--- /dev/null
+++ b/src/test/rustdoc/check.rs
@@ -0,0 +1,5 @@
+// compile-flags: -Z unstable-options --check
+
+// @!has check/fn.foo.html
+// @!has check/index.html
+pub fn foo() {}
diff --git a/src/test/ui/const-generics/promotion.rs b/src/test/ui/const-generics/promotion.rs
new file mode 100644
index 0000000000000..ac568bb75f002
--- /dev/null
+++ b/src/test/ui/const-generics/promotion.rs
@@ -0,0 +1,11 @@
+// run-pass
+// tests that promoting expressions containing const parameters is allowed.
+#![feature(min_const_generics)]
+
+fn promotion_test<const N: usize>() -> &'static usize {
+    &(3 + N)
+}
+
+fn main() {
+    assert_eq!(promotion_test::<13>(), &16);
+}
diff --git a/src/test/ui/issues/issue-38868.rs b/src/test/ui/dropck/issue-38868.rs
similarity index 100%
rename from src/test/ui/issues/issue-38868.rs
rename to src/test/ui/dropck/issue-38868.rs
diff --git a/src/test/ui/issues/issue-38868.stderr b/src/test/ui/dropck/issue-38868.stderr
similarity index 100%
rename from src/test/ui/issues/issue-38868.stderr
rename to src/test/ui/dropck/issue-38868.stderr
diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/dropck/reject-specialized-drops-8142.rs
similarity index 88%
rename from src/test/ui/reject-specialized-drops-8142.rs
rename to src/test/ui/dropck/reject-specialized-drops-8142.rs
index c4671736d79ec..02e8665cd2e3b 100644
--- a/src/test/ui/reject-specialized-drops-8142.rs
+++ b/src/test/ui/dropck/reject-specialized-drops-8142.rs
@@ -1,5 +1,6 @@
 // Issue 8142: Test that Drop impls cannot be specialized beyond the
 // predicates attached to the type definition itself.
+#![feature(min_const_generics)]
 
 trait Bound { fn foo(&self) { } }
 struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
@@ -15,6 +16,8 @@ struct T<'t,Ts:'t> { x: &'t Ts }
 struct U;
 struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
 struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct X<const Ca: usize>;
+struct Y<const Ca: usize, const Cb: usize>;
 
 enum Enum<T> { Variant(T) }
 struct TupleStruct<T>(T);
@@ -58,6 +61,12 @@ impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
 impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
 //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`
 
+impl              Drop for X<3>           { fn drop(&mut self) { } } // REJECT
+//~^ ERROR `Drop` impls cannot be specialized
+
+impl<const Ca: usize> Drop for Y<Ca, Ca>     { fn drop(&mut self) { } } // REJECT
+//~^ ERROR `Drop` impls cannot be specialized
+
 impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
 //~^ ERROR `Drop` impl requires `AddsBnd: Bound`
 
diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr
similarity index 71%
rename from src/test/ui/reject-specialized-drops-8142.stderr
rename to src/test/ui/dropck/reject-specialized-drops-8142.stderr
index eac2461753355..284cf59c822bd 100644
--- a/src/test/ui/reject-specialized-drops-8142.stderr
+++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr
@@ -1,151 +1,175 @@
 error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:23:20
+  --> $DIR/reject-specialized-drops-8142.rs:26:20
    |
 LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
    |                    ^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:5:1
+  --> $DIR/reject-specialized-drops-8142.rs:6:1
    |
 LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:27:67
+  --> $DIR/reject-specialized-drops-8142.rs:30:67
    |
 LL | impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
    |                                                                   ^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:6:1
+  --> $DIR/reject-specialized-drops-8142.rs:7:1
    |
 LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/reject-specialized-drops-8142.rs:33:1
+  --> $DIR/reject-specialized-drops-8142.rs:36:1
    |
 LL | impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected struct `N<'n>`
               found struct `N<'static>`
-note: the lifetime `'n` as defined on the struct at 8:10...
-  --> $DIR/reject-specialized-drops-8142.rs:8:10
+note: the lifetime `'n` as defined on the struct at 9:10...
+  --> $DIR/reject-specialized-drops-8142.rs:9:10
    |
 LL | struct N<'n> { x: &'n i8 }
    |          ^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:40:1
+  --> $DIR/reject-specialized-drops-8142.rs:43:1
    |
 LL | impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: use the same sequence of generic type, lifetime and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:10:1
+  --> $DIR/reject-specialized-drops-8142.rs:11:1
    |
 LL | struct P<Tp> { x: *const Tp }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:43:14
+  --> $DIR/reject-specialized-drops-8142.rs:46:14
    |
 LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
    |              ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:11:1
+  --> $DIR/reject-specialized-drops-8142.rs:12:1
    |
 LL | struct Q<Tq> { x: *const Tq }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:46:21
+  --> $DIR/reject-specialized-drops-8142.rs:49:21
    |
 LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
    |                     ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:12:1
+  --> $DIR/reject-specialized-drops-8142.rs:13:1
    |
 LL | struct R<Tr> { x: *const Tr }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:55:1
+  --> $DIR/reject-specialized-drops-8142.rs:58:1
    |
 LL | impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: use the same sequence of generic type, lifetime and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:16:1
+  --> $DIR/reject-specialized-drops-8142.rs:17:1
    |
 LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements
-  --> $DIR/reject-specialized-drops-8142.rs:58:1
+  --> $DIR/reject-specialized-drops-8142.rs:61:1
    |
 LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10...
-  --> $DIR/reject-specialized-drops-8142.rs:17:10
+note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 18:10...
+  --> $DIR/reject-specialized-drops-8142.rs:18:10
    |
 LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
    |          ^^^
-note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15...
-  --> $DIR/reject-specialized-drops-8142.rs:17:15
+note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 18:15...
+  --> $DIR/reject-specialized-drops-8142.rs:18:15
    |
 LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
    |               ^^^
 note: ...so that the types are compatible
-  --> $DIR/reject-specialized-drops-8142.rs:58:1
+  --> $DIR/reject-specialized-drops-8142.rs:61:1
    |
 LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `W<'l1, 'l2>`
               found `W<'_, '_>`
 
+error[E0366]: `Drop` impls cannot be specialized
+  --> $DIR/reject-specialized-drops-8142.rs:64:1
+   |
+LL | impl              Drop for X<3>           { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: use the same sequence of generic type, lifetime and const parameters as the struct definition
+  --> $DIR/reject-specialized-drops-8142.rs:19:1
+   |
+LL | struct X<const Ca: usize>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0366]: `Drop` impls cannot be specialized
+  --> $DIR/reject-specialized-drops-8142.rs:67:1
+   |
+LL | impl<const Ca: usize> Drop for Y<Ca, Ca>     { fn drop(&mut self) { } } // REJECT
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: use the same sequence of generic type, lifetime and const parameters as the struct definition
+  --> $DIR/reject-specialized-drops-8142.rs:20:1
+   |
+LL | struct Y<const Ca: usize, const Cb: usize>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:61:14
+  --> $DIR/reject-specialized-drops-8142.rs:70:14
    |
 LL | impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
    |              ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:19:1
+  --> $DIR/reject-specialized-drops-8142.rs:22:1
    |
 LL | enum Enum<T> { Variant(T) }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:64:14
+  --> $DIR/reject-specialized-drops-8142.rs:73:14
    |
 LL | impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
    |              ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:20:1
+  --> $DIR/reject-specialized-drops-8142.rs:23:1
    |
 LL | struct TupleStruct<T>(T);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:67:21
+  --> $DIR/reject-specialized-drops-8142.rs:76:21
    |
 LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
    |                     ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:21:1
+  --> $DIR/reject-specialized-drops-8142.rs:24:1
    |
 LL | union Union<T: Copy> { f: T }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0308, E0366, E0367, E0495.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-76042.rs b/src/test/ui/issues/issue-76042.rs
new file mode 100644
index 0000000000000..34d5293799aa7
--- /dev/null
+++ b/src/test/ui/issues/issue-76042.rs
@@ -0,0 +1,16 @@
+// run-pass
+// compile-flags: -Coverflow-checks=off -Ccodegen-units=1 -Copt-level=0
+
+fn foo(a: i128, b: i128, s: u32) -> (i128, i128) {
+    if s == 128 {
+        (0, 0)
+    } else {
+        (b >> s, a >> s)
+    }
+}
+fn main() {
+    let r = foo(0, 8, 1);
+    if r.0 != 4 {
+        panic!();
+    }
+}