about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-04 04:51:49 +0000
committerbors <bors@rust-lang.org>2020-12-04 04:51:49 +0000
commite9dd18ca749801a19d85bfb424ae12011a8ff894 (patch)
treeff6d9acd47c92008a14624ee9a038130fe7d1760
parent6513f5029183471993bab4b05ae5f5433f461b08 (diff)
parent5cebbaa6a1509ca17cef41ef61df624dad9740c2 (diff)
downloadrust-e9dd18ca749801a19d85bfb424ae12011a8ff894.tar.gz
rust-e9dd18ca749801a19d85bfb424ae12011a8ff894.zip
Auto merge of #79686 - Dylan-DPC:rollup-leama5f, r=Dylan-DPC
Rollup of 11 pull requests

Successful merges:

 - #77686 (Render Markdown in search results)
 - #79541 (Doc keyword lint pass)
 - #79602 (Fix SGX CI)
 - #79611 (Use more std:: instead of core:: in docs for consistency)
 - #79623 (Pass around Symbols instead of Idents in doctree)
 - #79627 (Update cargo)
 - #79631 (disable a ptr equality test on Miri)
 - #79638 (Use `item_name` instead of pretty printing for resolving `Self` on intra-doc links)
 - #79646 (rustc_metadata: Remove some dead code)
 - #79664 (move interpret::MemoryKind::Heap to const eval)
 - #79678 (Fix some clippy lints)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_expand/src/base.rs10
-rw-r--r--compiler/rustc_expand/src/expand.rs8
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_lexer/src/lib.rs10
-rw-r--r--compiler/rustc_lint/src/internal.rs46
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs12
-rw-r--r--compiler/rustc_middle/src/middle/cstore.rs2
-rw-r--r--compiler/rustc_mir/src/const_eval/machine.rs27
-rw-r--r--compiler/rustc_mir/src/interpret/intern.rs27
-rw-r--r--compiler/rustc_mir/src/interpret/machine.rs8
-rw-r--r--compiler/rustc_mir/src/interpret/memory.rs5
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs2
-rw-r--r--compiler/rustc_serialize/src/json.rs2
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs4
-rw-r--r--compiler/rustc_span/src/lib.rs5
-rw-r--r--compiler/rustc_span/src/source_map.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs14
-rw-r--r--library/alloc/tests/str.rs7
-rw-r--r--library/core/src/fmt/mod.rs2
-rw-r--r--library/core/src/future/pending.rs2
-rw-r--r--library/core/src/future/poll_fn.rs6
-rw-r--r--library/core/src/future/ready.rs2
-rw-r--r--library/core/src/panic.rs2
-rw-r--r--library/core/src/task/ready.rs19
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/primitive_docs.rs4
-rw-r--r--library/std/tests/env.rs5
-rw-r--r--src/librustdoc/clean/mod.rs17
-rw-r--r--src/librustdoc/core.rs1
-rw-r--r--src/librustdoc/doctree.rs8
-rw-r--r--src/librustdoc/formats/cache.rs8
-rw-r--r--src/librustdoc/html/markdown.rs90
-rw-r--r--src/librustdoc/html/markdown/tests.rs33
-rw-r--r--src/librustdoc/html/render/cache.rs6
-rw-r--r--src/librustdoc/html/render/mod.rs41
-rw-r--r--src/librustdoc/html/static/main.js23
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs13
-rw-r--r--src/librustdoc/visit_ast.rs18
-rw-r--r--src/test/rustdoc-js/basic.rs2
-rw-r--r--src/test/rustdoc-js/summaries.js21
-rw-r--r--src/test/rustdoc-js/summaries.rs18
-rw-r--r--src/test/rustdoc/intra-doc/raw-ident-self.rs13
-rw-r--r--src/test/rustdoc/markdown-summaries.rs (renamed from src/test/rustdoc/plain-text-summaries.rs)9
-rw-r--r--src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs11
-rw-r--r--src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr15
m---------src/tools/cargo0
49 files changed, 429 insertions, 179 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index b1071bf4308..335f3b7a9a0 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -235,12 +235,10 @@ impl Annotatable {
     pub fn derive_allowed(&self) -> bool {
         match *self {
             Annotatable::Stmt(ref stmt) => match stmt.kind {
-                ast::StmtKind::Item(ref item) => match item.kind {
-                    ast::ItemKind::Struct(..)
-                    | ast::ItemKind::Enum(..)
-                    | ast::ItemKind::Union(..) => true,
-                    _ => false,
-                },
+                ast::StmtKind::Item(ref item) => matches!(
+                    item.kind,
+                    ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..)
+                ),
                 _ => false,
             },
             Annotatable::Item(ref item) => match item.kind {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 37ff6b9b368..2da5bde028f 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1134,7 +1134,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
                 // Collect the invoc regardless of whether or not attributes are permitted here
                 // expansion will eat the attribute so it won't error later.
-                attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
+                if let Some(attr) = attr.0.as_ref() {
+                    self.cfg.maybe_emit_expr_attr_err(attr)
+                }
 
                 // AstFragmentKind::Expr requires the macro to emit an expression.
                 return self
@@ -1231,7 +1233,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             self.cfg.configure_expr_kind(&mut expr.kind);
 
             if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
-                attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
+                if let Some(attr) = attr.0.as_ref() {
+                    self.cfg.maybe_emit_expr_attr_err(attr)
+                }
 
                 return self
                     .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f01d4417105..44dc6673564 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2401,7 +2401,7 @@ impl StructField<'_> {
     // Still necessary in couple of places
     pub fn is_positional(&self) -> bool {
         let first = self.ident.as_str().as_bytes()[0];
-        first >= b'0' && first <= b'9'
+        (b'0'..=b'9').contains(&first)
     }
 }
 
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 6539419aefb..44fc4db7dc1 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -267,8 +267,8 @@ pub fn is_whitespace(c: char) -> bool {
 pub fn is_id_start(c: char) -> bool {
     // This is XID_Start OR '_' (which formally is not a XID_Start).
     // We also add fast-path for ascii idents
-    ('a' <= c && c <= 'z')
-        || ('A' <= c && c <= 'Z')
+    ('a'..='z').contains(&c)
+        || ('A'..='Z').contains(&c)
         || c == '_'
         || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c))
 }
@@ -279,9 +279,9 @@ pub fn is_id_start(c: char) -> bool {
 pub fn is_id_continue(c: char) -> bool {
     // This is exactly XID_Continue.
     // We also add fast-path for ascii idents
-    ('a' <= c && c <= 'z')
-        || ('A' <= c && c <= 'Z')
-        || ('0' <= c && c <= '9')
+    ('a'..='z').contains(&c)
+        || ('A'..='Z').contains(&c)
+        || ('0'..='9').contains(&c)
         || c == '_'
         || (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
 }
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index c2d98b8e4ad..af5972c6c81 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -10,7 +10,7 @@ use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath,
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
@@ -267,3 +267,47 @@ impl EarlyLintPass for LintPassImpl {
         }
     }
 }
+
+declare_tool_lint! {
+    pub rustc::EXISTING_DOC_KEYWORD,
+    Allow,
+    "Check that documented keywords in std and core actually exist",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(ExistingDocKeyword => [EXISTING_DOC_KEYWORD]);
+
+fn is_doc_keyword(s: Symbol) -> bool {
+    s <= kw::Union
+}
+
+impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
+        for attr in item.attrs {
+            if !attr.has_name(sym::doc) {
+                continue;
+            }
+            if let Some(list) = attr.meta_item_list() {
+                for nested in list {
+                    if nested.has_name(sym::keyword) {
+                        let v = nested
+                            .value_str()
+                            .expect("#[doc(keyword = \"...\")] expected a value!");
+                        if is_doc_keyword(v) {
+                            return;
+                        }
+                        cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
+                            lint.build(&format!(
+                                "Found non-existing keyword `{}` used in \
+                                     `#[doc(keyword = \"...\")]`",
+                                v,
+                            ))
+                            .help("only existing keywords are allowed in core/std")
+                            .emit();
+                        });
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 81549be4b09..80ef855c385 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -463,6 +463,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_early_pass(|| box DefaultHashTypes::new());
     store.register_lints(&LintPassImpl::get_lints());
     store.register_early_pass(|| box LintPassImpl);
+    store.register_lints(&ExistingDocKeyword::get_lints());
+    store.register_late_pass(|| box ExistingDocKeyword);
     store.register_lints(&TyTyKind::get_lints());
     store.register_late_pass(|| box TyTyKind);
     store.register_group(
@@ -475,6 +477,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(TY_PASS_BY_REFERENCE),
             LintId::of(USAGE_OF_QUALIFIED_TY),
+            LintId::of(EXISTING_DOC_KEYWORD),
         ],
     );
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f53a4027806..c571ed7b612 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1592,23 +1592,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
-    fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
-        let mut def_path_hashes = self.def_path_hash_cache.lock();
-        let mut def_index_to_data = |index| {
-            (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
-        };
-        if let Some(data) = &self.root.proc_macro_data {
-            std::iter::once(CRATE_DEF_INDEX)
-                .chain(data.macros.decode(self))
-                .map(def_index_to_data)
-                .collect()
-        } else {
-            (0..self.num_def_ids())
-                .map(|index| def_index_to_data(DefIndex::from_usize(index)))
-                .collect()
-        }
-    }
-
     /// Get the `DepNodeIndex` corresponding this crate. The result of this
     /// method is cached in the `dep_node_index` field.
     fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 2ffd239b2f0..b7f22885217 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -456,6 +456,10 @@ impl CStore {
     pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId {
         self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess)
     }
+
+    pub fn num_def_ids(&self, cnum: CrateNum) -> usize {
+        self.get_crate_data(cnum).num_def_ids()
+    }
 }
 
 impl CrateStore for CStore {
@@ -498,14 +502,6 @@ impl CrateStore for CStore {
         self.get_crate_data(def.krate).def_path_hash(def.index)
     }
 
-    fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
-        self.get_crate_data(cnum).all_def_path_hashes_and_def_ids()
-    }
-
-    fn num_def_ids(&self, cnum: CrateNum) -> usize {
-        self.get_crate_data(cnum).num_def_ids()
-    }
-
     // See `CrateMetadataRef::def_path_hash_to_def_id` for more details
     fn def_path_hash_to_def_id(
         &self,
diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs
index bd7121ca1d7..6d2c43874bc 100644
--- a/compiler/rustc_middle/src/middle/cstore.rs
+++ b/compiler/rustc_middle/src/middle/cstore.rs
@@ -189,8 +189,6 @@ pub trait CrateStore {
     fn def_kind(&self, def: DefId) -> DefKind;
     fn def_path(&self, def: DefId) -> DefPath;
     fn def_path_hash(&self, def: DefId) -> DefPathHash;
-    fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
-    fn num_def_ids(&self, cnum: CrateNum) -> usize;
     fn def_path_hash_to_def_id(
         &self,
         cnum: CrateNum,
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index 275496647d9..187f6fab518 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -7,6 +7,7 @@ use std::collections::hash_map::Entry;
 use std::hash::Hash;
 
 use rustc_data_structures::fx::FxHashMap;
+use std::fmt;
 
 use rustc_ast::Mutability;
 use rustc_hir::def_id::DefId;
@@ -179,6 +180,28 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
 crate type CompileTimeEvalContext<'mir, 'tcx> =
     InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
 
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub enum MemoryKind {
+    Heap,
+}
+
+impl fmt::Display for MemoryKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            MemoryKind::Heap => write!(f, "heap allocation"),
+        }
+    }
+}
+
+impl interpret::MayLeak for MemoryKind {
+    #[inline(always)]
+    fn may_leak(self) -> bool {
+        match self {
+            MemoryKind::Heap => false,
+        }
+    }
+}
+
 impl interpret::MayLeak for ! {
     #[inline(always)]
     fn may_leak(self) -> bool {
@@ -222,6 +245,8 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
 impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
     compile_time_machine!(<'mir, 'tcx>);
 
+    type MemoryKind = MemoryKind;
+
     type MemoryExtra = MemoryExtra;
 
     fn find_mir_or_eval_fn(
@@ -317,7 +342,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                 let ptr = ecx.memory.allocate(
                     Size::from_bytes(size as u64),
                     align,
-                    interpret::MemoryKind::ConstHeap,
+                    interpret::MemoryKind::Machine(MemoryKind::Heap),
                 );
                 ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
             }
diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs
index db996f72128..01d58c47e3a 100644
--- a/compiler/rustc_mir/src/interpret/intern.rs
+++ b/compiler/rustc_mir/src/interpret/intern.rs
@@ -25,19 +25,20 @@ use rustc_target::abi::Size;
 use rustc_ast::Mutability;
 
 use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
+use crate::const_eval;
 
-pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
+pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
     'mir,
     'tcx,
-    MemoryKind = !,
+    MemoryKind = T,
     PointerTag = (),
     ExtraFnVal = !,
     FrameExtra = (),
     AllocExtra = (),
-    MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
+    MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>,
 >;
 
-struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
+struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
     /// The ectx from which we intern.
     ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
     /// Previously encountered safe references.
@@ -74,7 +75,7 @@ struct IsStaticOrFn;
 /// `immutable` things might become mutable if `ty` is not frozen.
 /// `ty` can be `None` if there is no potential interior mutability
 /// to account for (e.g. for vtables).
-fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
+fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
     ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
     leftover_allocations: &'rt mut FxHashSet<AllocId>,
     alloc_id: AllocId,
@@ -105,7 +106,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
     // changes in this function.
     match kind {
         MemoryKind::Stack
-        | MemoryKind::ConstHeap
+        | MemoryKind::Machine(const_eval::MemoryKind::Heap)
         | MemoryKind::Vtable
         | MemoryKind::CallerLocation => {}
     }
@@ -141,7 +142,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
     None
 }
 
-impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> {
+impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
+    InternVisitor<'rt, 'mir, 'tcx, M>
+{
     fn intern_shallow(
         &mut self,
         alloc_id: AllocId,
@@ -152,8 +155,8 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir
     }
 }
 
-impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
-    for InternVisitor<'rt, 'mir, 'tcx, M>
+impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
+    ValueVisitor<'mir, 'tcx, M> for InternVisitor<'rt, 'mir, 'tcx, M>
 {
     type V = MPlaceTy<'tcx>;
 
@@ -290,7 +293,7 @@ pub enum InternKind {
 /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
 /// are hard errors.
 #[tracing::instrument(skip(ecx))]
-pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
+pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
     ecx: &mut InterpCx<'mir, 'tcx, M>,
     intern_kind: InternKind,
     ret: MPlaceTy<'tcx>,
@@ -421,7 +424,9 @@ where
     Ok(())
 }
 
-impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
+    InterpCx<'mir, 'tcx, M>
+{
     /// A helper function that allocates memory for the layout given and gives you access to mutate
     /// it. Once your own mutation code is done, the backing `Allocation` is removed from the
     /// current `Memory` and returned.
diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs
index 66dbacb2f9d..0bba0273772 100644
--- a/compiler/rustc_mir/src/interpret/machine.rs
+++ b/compiler/rustc_mir/src/interpret/machine.rs
@@ -366,9 +366,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     type PointerTag = ();
     type ExtraFnVal = !;
 
-    type MemoryKind = !;
-    type MemoryMap = rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
-    const GLOBAL_KIND: Option<!> = None; // no copying of globals from `tcx` to machine memory
+    type MemoryMap =
+        rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
+    const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
 
     type AllocExtra = ();
     type FrameExtra = ();
@@ -407,7 +407,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
         _memory_extra: &Self::MemoryExtra,
         _id: AllocId,
         alloc: Cow<'b, Allocation>,
-        _kind: Option<MemoryKind<!>>,
+        _kind: Option<MemoryKind<Self::MemoryKind>>,
     ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
         // We do not use a tag so we can just cheaply forward the allocation
         (alloc, ())
diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs
index 3294daabe61..f3e373813ca 100644
--- a/compiler/rustc_mir/src/interpret/memory.rs
+++ b/compiler/rustc_mir/src/interpret/memory.rs
@@ -27,9 +27,6 @@ use crate::util::pretty;
 pub enum MemoryKind<T> {
     /// Stack memory. Error if deallocated except during a stack pop.
     Stack,
-    /// Heap memory.
-    /// FIXME: this variant should be in const_eval
-    ConstHeap,
     /// Memory backing vtables. Error if ever deallocated.
     Vtable,
     /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
@@ -43,7 +40,6 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
     fn may_leak(self) -> bool {
         match self {
             MemoryKind::Stack => false,
-            MemoryKind::ConstHeap => false,
             MemoryKind::Vtable => true,
             MemoryKind::CallerLocation => true,
             MemoryKind::Machine(k) => k.may_leak(),
@@ -55,7 +51,6 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             MemoryKind::Stack => write!(f, "stack variable"),
-            MemoryKind::ConstHeap => write!(f, "heap allocation"),
             MemoryKind::Vtable => write!(f, "vtable"),
             MemoryKind::CallerLocation => write!(f, "caller location"),
             MemoryKind::Machine(m) => write!(f, "{}", m),
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index abcf1862fd8..1d949e020ed 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -180,6 +180,8 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
 impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
     compile_time_machine!(<'mir, 'tcx>);
 
+    type MemoryKind = !;
+
     type MemoryExtra = ();
 
     fn find_mir_or_eval_fn(
diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs
index 6c8965aa2e3..bbbe568f17a 100644
--- a/compiler/rustc_serialize/src/json.rs
+++ b/compiler/rustc_serialize/src/json.rs
@@ -1859,7 +1859,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
                             }
 
                             let n2 = self.decode_hex_escape()?;
-                            if n2 < 0xDC00 || n2 > 0xDFFF {
+                            if !(0xDC00..=0xDFFF).contains(&n2) {
                                 return self.error(LoneLeadingSurrogateInHexEscape);
                             }
                             let c =
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index b4beb3dc376..5987fb2a198 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -97,7 +97,7 @@ cfg_if::cfg_if! {
                 let ptr = src_bytes.as_ptr() as *const __m128i;
                 // We don't know if the pointer is aligned to 16 bytes, so we
                 // use `loadu`, which supports unaligned loading.
-                let chunk = _mm_loadu_si128(ptr.offset(chunk_index as isize));
+                let chunk = _mm_loadu_si128(ptr.add(chunk_index));
 
                 // For character in the chunk, see if its byte value is < 0, which
                 // indicates that it's part of a UTF-8 char.
@@ -253,7 +253,7 @@ fn analyze_source_file_generic(
             let pos = BytePos::from_usize(i) + output_offset;
 
             if char_len > 1 {
-                assert!(char_len >= 2 && char_len <= 4);
+                assert!((2..=4).contains(&char_len));
                 let mbc = MultiByteChar { pos, bytes: char_len as u8 };
                 multi_byte_chars.push(mbc);
             }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 11a49d1ab88..f63a73acbf4 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1015,10 +1015,7 @@ pub enum ExternalSourceKind {
 
 impl ExternalSource {
     pub fn is_absent(&self) -> bool {
-        match self {
-            ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false,
-            _ => true,
-        }
+        !matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. })
     }
 
     pub fn get_source(&self) -> Option<&Lrc<String>> {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index f067cdb7308..e9b4eb6e4ab 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -623,7 +623,7 @@ impl SourceMap {
         self.span_to_source(sp, |src, start_index, end_index| {
             src.get(start_index..end_index)
                 .map(|s| s.to_string())
-                .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))
+                .ok_or(SpanSnippetError::IllFormedSpan(sp))
         })
     }
 
@@ -640,9 +640,7 @@ impl SourceMap {
     /// Returns the source snippet as `String` before the given `Span`.
     pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
         self.span_to_source(sp, |src, start_index, _| {
-            src.get(..start_index)
-                .map(|s| s.to_string())
-                .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))
+            src.get(..start_index).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
         })
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 91b87fdc482..e75ddb36ff8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1363,15 +1363,13 @@ impl fmt::Display for IdentPrinter {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if self.is_raw {
             f.write_str("r#")?;
-        } else {
-            if self.symbol == kw::DollarCrate {
-                if let Some(span) = self.convert_dollar_crate {
-                    let converted = span.ctxt().dollar_crate_name();
-                    if !converted.is_path_segment_keyword() {
-                        f.write_str("::")?;
-                    }
-                    return fmt::Display::fmt(&converted, f);
+        } else if self.symbol == kw::DollarCrate {
+            if let Some(span) = self.convert_dollar_crate {
+                let converted = span.ctxt().dollar_crate_name();
+                if !converted.is_path_segment_keyword() {
+                    f.write_str("::")?;
                 }
+                return fmt::Display::fmt(&converted, f);
             }
         }
         fmt::Display::fmt(&self.symbol, f)
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index b1301914656..604835e6cc4 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1978,9 +1978,14 @@ fn const_str_ptr() {
     const B: &'static [u8; 2] = &A;
     const C: *const u8 = B as *const u8;
 
-    unsafe {
+    // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
+    #[cfg(not(miri))]
+    {
         let foo = &A as *const u8;
         assert_eq!(foo, C);
+    }
+
+    unsafe {
         assert_eq!(from_utf8_unchecked(&A), "hi");
         assert_eq!(*C, A[0]);
         assert_eq!(*(&B[0] as *const u8), A[0]);
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 4ed62a620c4..0c65c1c9eb7 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -403,7 +403,7 @@ impl<'a> Arguments<'a> {
     /// ```rust
     /// #![feature(fmt_as_str)]
     ///
-    /// use core::fmt::Arguments;
+    /// use std::fmt::Arguments;
     ///
     /// fn write_str(_: &str) { /* ... */ }
     ///
diff --git a/library/core/src/future/pending.rs b/library/core/src/future/pending.rs
index ab162638a1c..560dd25ecff 100644
--- a/library/core/src/future/pending.rs
+++ b/library/core/src/future/pending.rs
@@ -21,7 +21,7 @@ pub struct Pending<T> {
 /// # Examples
 ///
 /// ```no_run
-/// use core::future;
+/// use std::future;
 ///
 /// # async fn run() {
 /// let future = future::pending();
diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs
index af63e1bb097..9ae118e29f1 100644
--- a/library/core/src/future/poll_fn.rs
+++ b/library/core/src/future/poll_fn.rs
@@ -3,7 +3,7 @@ use crate::future::Future;
 use crate::pin::Pin;
 use crate::task::{Context, Poll};
 
-/// Creates a future that wraps a function returning `Poll`.
+/// Creates a future that wraps a function returning [`Poll`].
 ///
 /// Polling the future delegates to the wrapped function.
 ///
@@ -13,7 +13,7 @@ use crate::task::{Context, Poll};
 /// #![feature(future_poll_fn)]
 /// # async fn run() {
 /// use core::future::poll_fn;
-/// use core::task::{Context, Poll};
+/// use std::task::{Context, Poll};
 ///
 /// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
 ///     Poll::Ready("Hello, World!".into())
@@ -31,7 +31,7 @@ where
     PollFn { f }
 }
 
-/// A Future that wraps a function returning `Poll`.
+/// A Future that wraps a function returning [`Poll`].
 ///
 /// This `struct` is created by [`poll_fn()`]. See its
 /// documentation for more.
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs
index e98f5c570bf..b0c7fbb1d7a 100644
--- a/library/core/src/future/ready.rs
+++ b/library/core/src/future/ready.rs
@@ -33,7 +33,7 @@ impl<T> Future for Ready<T> {
 /// # Examples
 ///
 /// ```
-/// use core::future;
+/// use std::future;
 ///
 /// # async fn run() {
 /// let a = future::ready(1);
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 34a974b8271..03bb849509a 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -189,7 +189,7 @@ impl<'a> Location<'a> {
     /// # Examples
     ///
     /// ```
-    /// use core::panic::Location;
+    /// use std::panic::Location;
     ///
     /// /// Returns the [`Location`] at which it is called.
     /// #[track_caller]
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index e221aaf3fd6..cbf69900015 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,15 +1,18 @@
-/// Extracts the successful type of a `Poll<T>`.
+/// Extracts the successful type of a [`Poll<T>`].
 ///
-/// This macro bakes in propagation of `Pending` signals by returning early.
+/// This macro bakes in propagation of [`Pending`] signals by returning early.
+///
+/// [`Poll<T>`]: crate::task::Poll
+/// [`Pending`]: crate::task::Poll::Pending
 ///
 /// # Examples
 ///
 /// ```
 /// #![feature(ready_macro)]
 ///
-/// use core::task::{ready, Context, Poll};
-/// use core::future::{self, Future};
-/// use core::pin::Pin;
+/// use std::task::{ready, Context, Poll};
+/// use std::future::{self, Future};
+/// use std::pin::Pin;
 ///
 /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
 ///     let mut fut = future::ready(42);
@@ -28,9 +31,9 @@
 /// ```
 /// # #![feature(ready_macro)]
 /// #
-/// # use core::task::{Context, Poll};
-/// # use core::future::{self, Future};
-/// # use core::pin::Pin;
+/// # use std::task::{Context, Poll};
+/// # use std::future::{self, Future};
+/// # use std::pin::Pin;
 /// #
 /// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
 ///     # let mut fut = future::ready(42);
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 83eb847697d..6c240cb4c3e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -212,6 +212,7 @@
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
+#![deny(rustc::existing_doc_keyword)]
 #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))]
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 83a282c8cd6..55171ef2292 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -198,7 +198,7 @@ mod prim_bool {}
 /// words, they can't return `!` from every code path. As an example, this code doesn't compile:
 ///
 /// ```compile_fail
-/// use core::ops::Add;
+/// use std::ops::Add;
 ///
 /// fn foo() -> impl Add<u32> {
 ///     unimplemented!()
@@ -208,7 +208,7 @@ mod prim_bool {}
 /// But this code does:
 ///
 /// ```
-/// use core::ops::Add;
+/// use std::ops::Add;
 ///
 /// fn foo() -> impl Add<u32> {
 ///     if true {
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index 0e55ec648c9..76056637a4c 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -1,6 +1,5 @@
 use std::env::*;
 use std::ffi::{OsStr, OsString};
-use std::path::PathBuf;
 
 use rand::distributions::Alphanumeric;
 use rand::{thread_rng, Rng};
@@ -92,6 +91,8 @@ fn env_home_dir() {
 
     cfg_if::cfg_if! {
         if #[cfg(unix)] {
+            use std::path::PathBuf;
+
             let oldhome = var_to_os_string(var("HOME"));
 
             set_var("HOME", "/home/MountainView");
@@ -109,6 +110,8 @@ fn env_home_dir() {
 
             if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
         } else if #[cfg(windows)] {
+            use std::path::PathBuf;
+
             let oldhome = var_to_os_string(var("HOME"));
             let olduserprofile = var_to_os_string(var("USERPROFILE"));
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a3c28be3137..8c344338de7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1000,7 +1000,7 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
                     .iter()
                     .map(|t| Argument {
                         type_: t.clean(cx),
-                        name: names.next().map_or(String::new(), |name| name.to_string()),
+                        name: names.next().map_or_else(|| String::new(), |name| name.to_string()),
                     })
                     .collect(),
             },
@@ -1974,16 +1974,13 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     }
 }
 
-impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Ident>) {
+impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
     fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
         use hir::ItemKind;
 
         let (item, renamed) = self;
         let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
-        let mut name = match renamed {
-            Some(ident) => ident.name,
-            None => cx.tcx.hir().name(item.hir_id),
-        };
+        let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id));
         cx.with_param_env(def_id, || {
             let kind = match item.kind {
                 ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
@@ -2276,7 +2273,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
     }
 }
 
-impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
+impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let (item, renamed) = self;
         cx.with_param_env(cx.tcx.hir().local_def_id(item.hir_id).to_def_id(), || {
@@ -2310,7 +2307,7 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
 
             Item::from_hir_id_and_parts(
                 item.hir_id,
-                Some(renamed.unwrap_or(item.ident).name),
+                Some(renamed.unwrap_or(item.ident.name)),
                 kind,
                 cx,
             )
@@ -2318,10 +2315,10 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
     }
 }
 
-impl Clean<Item> for (&hir::MacroDef<'_>, Option<Ident>) {
+impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let (item, renamed) = self;
-        let name = renamed.unwrap_or(item.ident).name;
+        let name = renamed.unwrap_or(item.ident.name);
         let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
         // Extract the spans of all matchers. They represent the "interface" of the macro.
         let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::<Vec<_>>();
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index eecdc929ab6..9c693c290e7 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -13,7 +13,6 @@ use rustc_hir::{
 };
 use rustc_interface::interface;
 use rustc_middle::hir::map::Map;
-use rustc_middle::middle::cstore::CrateStore;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_resolve as resolve;
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 3961870a1bf..ee9a6981857 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -3,7 +3,7 @@
 crate use self::StructType::*;
 
 use rustc_ast as ast;
-use rustc_span::{self, symbol::Ident, Span, Symbol};
+use rustc_span::{self, Span, Symbol};
 
 use rustc_hir as hir;
 
@@ -16,9 +16,9 @@ crate struct Module<'hir> {
     crate mods: Vec<Module<'hir>>,
     crate id: hir::HirId,
     // (item, renamed)
-    crate items: Vec<(&'hir hir::Item<'hir>, Option<Ident>)>,
-    crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Ident>)>,
-    crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Ident>)>,
+    crate items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
+    crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
+    crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Symbol>)>,
     crate is_crate: bool,
 }
 
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c3153f2d4b6..e82bc540e95 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -14,13 +14,13 @@ use crate::config::RenderInfo;
 use crate::fold::DocFolder;
 use crate::formats::item_type::ItemType;
 use crate::formats::Impl;
+use crate::html::markdown::short_markdown_summary;
 use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation};
 use crate::html::render::IndexItem;
-use crate::html::render::{plain_text_summary, shorten};
 
 thread_local!(crate static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 
-/// This cache is used to store information about the `clean::Crate` being
+/// This cache is used to store information about the [`clean::Crate`] being
 /// rendered in order to provide more useful documentation. This contains
 /// information like all implementors of a trait, all traits a type implements,
 /// documentation for all known traits, etc.
@@ -313,7 +313,9 @@ impl DocFolder for Cache {
                             ty: item.type_(),
                             name: s.to_string(),
                             path: path.join("::"),
-                            desc: shorten(plain_text_summary(item.doc_value())),
+                            desc: item
+                                .doc_value()
+                                .map_or_else(|| String::new(), short_markdown_summary),
                             parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 8ce686c6550..0e4c5410abe 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -17,8 +17,6 @@
 //! // ... something using html
 //! ```
 
-#![allow(non_camel_case_types)]
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
@@ -1037,7 +1035,95 @@ impl MarkdownSummaryLine<'_> {
     }
 }
 
+/// Renders a subset of Markdown in the first paragraph of the provided Markdown.
+///
+/// - *Italics*, **bold**, and `inline code` styles **are** rendered.
+/// - Headings and links are stripped (though the text *is* rendered).
+/// - HTML, code blocks, and everything else are ignored.
+///
+/// Returns a tuple of the rendered HTML string and whether the output was shortened
+/// due to the provided `length_limit`.
+fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) {
+    if md.is_empty() {
+        return (String::new(), false);
+    }
+
+    let mut s = String::with_capacity(md.len() * 3 / 2);
+    let mut text_length = 0;
+    let mut stopped_early = false;
+
+    fn push(s: &mut String, text_length: &mut usize, text: &str) {
+        s.push_str(text);
+        *text_length += text.len();
+    };
+
+    'outer: for event in Parser::new_ext(md, Options::ENABLE_STRIKETHROUGH) {
+        match &event {
+            Event::Text(text) => {
+                for word in text.split_inclusive(char::is_whitespace) {
+                    if text_length + word.len() >= length_limit {
+                        stopped_early = true;
+                        break 'outer;
+                    }
+
+                    push(&mut s, &mut text_length, word);
+                }
+            }
+            Event::Code(code) => {
+                if text_length + code.len() >= length_limit {
+                    stopped_early = true;
+                    break;
+                }
+
+                s.push_str("<code>");
+                push(&mut s, &mut text_length, code);
+                s.push_str("</code>");
+            }
+            Event::Start(tag) => match tag {
+                Tag::Emphasis => s.push_str("<em>"),
+                Tag::Strong => s.push_str("<strong>"),
+                Tag::CodeBlock(..) => break,
+                _ => {}
+            },
+            Event::End(tag) => match tag {
+                Tag::Emphasis => s.push_str("</em>"),
+                Tag::Strong => s.push_str("</strong>"),
+                Tag::Paragraph => break,
+                _ => {}
+            },
+            Event::HardBreak | Event::SoftBreak => {
+                if text_length + 1 >= length_limit {
+                    stopped_early = true;
+                    break;
+                }
+
+                push(&mut s, &mut text_length, " ");
+            }
+            _ => {}
+        }
+    }
+
+    (s, stopped_early)
+}
+
+/// Renders a shortened first paragraph of the given Markdown as a subset of Markdown,
+/// making it suitable for contexts like the search index.
+///
+/// Will shorten to 59 or 60 characters, including an ellipsis (…) if it was shortened.
+///
+/// See [`markdown_summary_with_limit`] for details about what is rendered and what is not.
+crate fn short_markdown_summary(markdown: &str) -> String {
+    let (mut s, was_shortened) = markdown_summary_with_limit(markdown, 59);
+
+    if was_shortened {
+        s.push('…');
+    }
+
+    s
+}
+
 /// Renders the first paragraph of the provided markdown as plain text.
+/// Useful for alt-text.
 ///
 /// - Headings, links, and formatting are stripped.
 /// - Inline code is rendered as-is, surrounded by backticks.
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 8e618733f07..9807d8632c7 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -1,4 +1,4 @@
-use super::plain_text_summary;
+use super::{plain_text_summary, short_markdown_summary};
 use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use std::cell::RefCell;
@@ -205,6 +205,33 @@ fn test_header_ids_multiple_blocks() {
 }
 
 #[test]
+fn test_short_markdown_summary() {
+    fn t(input: &str, expect: &str) {
+        let output = short_markdown_summary(input);
+        assert_eq!(output, expect, "original: {}", input);
+    }
+
+    t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
+    t("*italic*", "<em>italic</em>");
+    t("**bold**", "<strong>bold</strong>");
+    t("Multi-line\nsummary", "Multi-line summary");
+    t("Hard-break  \nsummary", "Hard-break summary");
+    t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
+    t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
+    t("code `let x = i32;` ...", "code <code>let x = i32;</code> ...");
+    t("type `Type<'static>` ...", "type <code>Type<'static></code> ...");
+    t("# top header", "top header");
+    t("## header", "header");
+    t("first paragraph\n\nsecond paragraph", "first paragraph");
+    t("```\nfn main() {}\n```", "");
+    t("<div>hello</div>", "");
+    t(
+        "a *very*, **very** long first paragraph. it has lots of `inline code: Vec<T>`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break!  \nthat was a hard one\n\nsecond paragraph.",
+        "a <em>very</em>, <strong>very</strong> long first paragraph. it has lots of …",
+    );
+}
+
+#[test]
 fn test_plain_text_summary() {
     fn t(input: &str, expect: &str) {
         let output = plain_text_summary(input);
@@ -224,6 +251,10 @@ fn test_plain_text_summary() {
     t("first paragraph\n\nsecond paragraph", "first paragraph");
     t("```\nfn main() {}\n```", "");
     t("<div>hello</div>", "");
+    t(
+        "a *very*, **very** long first paragraph. it has lots of `inline code: Vec<T>`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break!  \nthat was a hard one\n\nsecond paragraph.",
+        "a very, very long first paragraph. it has lots of `inline code: Vec<T>`. and it has a link. that was a soft line break! that was a hard one",
+    );
 }
 
 #[test]
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 085ca01f58d..97f764517fa 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -9,7 +9,7 @@ use crate::clean::types::GetDefId;
 use crate::clean::{self, AttributesExt};
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
-use crate::html::render::{plain_text_summary, shorten};
+use crate::html::markdown::short_markdown_summary;
 use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
 
 /// Indicates where an external crate can be found.
@@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
                 ty: item.type_(),
                 name: item.name.clone().unwrap(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: shorten(plain_text_summary(item.doc_value())),
+                desc: item.doc_value().map_or_else(|| String::new(), short_markdown_summary),
                 parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item),
@@ -127,7 +127,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let crate_doc = krate
         .module
         .as_ref()
-        .map(|module| shorten(plain_text_summary(module.doc_value())))
+        .map(|module| module.doc_value().map_or_else(|| String::new(), short_markdown_summary))
         .unwrap_or_default();
 
     #[derive(Serialize)]
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index de620a35c80..901f00b21da 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -76,7 +76,9 @@ use crate::html::format::fmt_impl_for_trait_page;
 use crate::html::format::Function;
 use crate::html::format::{href, print_default_space, print_generic_bounds, WhereClause};
 use crate::html::format::{print_abi_with_space, Buffer, PrintWithSpace};
-use crate::html::markdown::{self, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
+use crate::html::markdown::{
+    self, plain_text_summary, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine,
+};
 use crate::html::sources;
 use crate::html::{highlight, layout, static_files};
 use cache::{build_index, ExternalLocation};
@@ -1604,9 +1606,10 @@ impl Context {
                 Some(ref s) => s.to_string(),
             };
             let short = short.to_string();
-            map.entry(short)
-                .or_default()
-                .push((myname, Some(plain_text_summary(item.doc_value()))));
+            map.entry(short).or_default().push((
+                myname,
+                Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)),
+            ));
         }
 
         if self.shared.sort_modules_alphabetically {
@@ -1810,36 +1813,6 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
     s
 }
 
-/// Renders the first paragraph of the given markdown as plain text, making it suitable for
-/// contexts like alt-text or the search index.
-///
-/// If no markdown is supplied, the empty string is returned.
-///
-/// See [`markdown::plain_text_summary`] for further details.
-#[inline]
-crate fn plain_text_summary(s: Option<&str>) -> String {
-    s.map(markdown::plain_text_summary).unwrap_or_default()
-}
-
-crate fn shorten(s: String) -> String {
-    if s.chars().count() > 60 {
-        let mut len = 0;
-        let mut ret = s
-            .split_whitespace()
-            .take_while(|p| {
-                // + 1 for the added character after the word.
-                len += p.chars().count() + 1;
-                len < 60
-            })
-            .collect::<Vec<_>>()
-            .join(" ");
-        ret.push('…');
-        ret
-    } else {
-        s
-    }
-}
-
 fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 69984be5eb6..0884351a9fd 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1611,7 +1611,7 @@ function defocusSearchBar() {
                               item.displayPath + "<span class=\"" + type + "\">" +
                               name + "</span></a></td><td>" +
                               "<a href=\"" + item.href + "\">" +
-                              "<span class=\"desc\">" + escape(item.desc) +
+                              "<span class=\"desc\">" + item.desc +
                               "&nbsp;</span></a></td></tr>";
                 });
                 output += "</table>";
@@ -2013,7 +2013,9 @@ function defocusSearchBar() {
                     }
                     var link = document.createElement("a");
                     link.href = rootPath + crates[i] + "/index.html";
-                    link.title = rawSearchIndex[crates[i]].doc;
+                    // The summary in the search index has HTML, so we need to
+                    // dynamically render it as plaintext.
+                    link.title = convertHTMLToPlaintext(rawSearchIndex[crates[i]].doc);
                     link.className = klass;
                     link.textContent = crates[i];
 
@@ -2026,6 +2028,23 @@ function defocusSearchBar() {
         }
     };
 
+    /**
+     * Convert HTML to plaintext:
+     *
+     *   * Replace "<code>foo</code>" with "`foo`"
+     *   * Strip all other HTML tags
+     *
+     * Used by the dynamic sidebar crate list renderer.
+     *
+     * @param  {[string]} html [The HTML to convert]
+     * @return {[string]}      [The resulting plaintext]
+     */
+    function convertHTMLToPlaintext(html) {
+        var x = document.createElement("div");
+        x.innerHTML = html.replace('<code>', '`').replace('</code>', '`');
+        return x.innerText;
+    }
+
 
     // delayed sidebar rendering.
     window.initSidebarItems = function(items) {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 80a9c3811cf..26bf4b569ff 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -15,6 +15,7 @@
 #![feature(never_type)]
 #![feature(once_cell)]
 #![feature(type_ascription)]
+#![feature(split_inclusive)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 3dcc0f240a3..551c086a8d4 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -847,12 +847,17 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
 
         // FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
         let self_name = self_id.and_then(|self_id| {
+            use ty::TyKind;
             if matches!(self.cx.tcx.def_kind(self_id), DefKind::Impl) {
-                // using `ty.to_string()` directly has issues with shortening paths
+                // using `ty.to_string()` (or any variant) has issues with raw idents
                 let ty = self.cx.tcx.type_of(self_id);
-                let name = ty::print::with_crate_prefix(|| ty.to_string());
-                debug!("using type_of(): {}", name);
-                Some(name)
+                let name = match ty.kind() {
+                    TyKind::Adt(def, _) => Some(self.cx.tcx.item_name(def.did).to_string()),
+                    other if other.is_primitive() => Some(ty.to_string()),
+                    _ => None,
+                };
+                debug!("using type_of(): {:?}", name);
+                name
             } else {
                 let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string());
                 debug!("using item_name(): {:?}", name);
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 4028293076d..f9cb1d586b1 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -10,7 +10,7 @@ use rustc_hir::Node;
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{self, Span};
 
 use std::mem;
@@ -116,7 +116,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         &mut self,
         id: hir::HirId,
         res: Res,
-        renamed: Option<Ident>,
+        renamed: Option<Symbol>,
         glob: bool,
         om: &mut Module<'tcx>,
         please_inline: bool,
@@ -226,11 +226,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     fn visit_item(
         &mut self,
         item: &'tcx hir::Item<'_>,
-        renamed: Option<Ident>,
+        renamed: Option<Symbol>,
         om: &mut Module<'tcx>,
     ) {
         debug!("visiting item {:?}", item);
-        let ident = renamed.unwrap_or(item.ident);
+        let name = renamed.unwrap_or(item.ident.name);
 
         if item.vis.node.is_pub() {
             let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
@@ -266,7 +266,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                         }
                         _ => false,
                     });
-                    let ident = if is_glob { None } else { Some(ident) };
+                    let ident = if is_glob { None } else { Some(name) };
                     if self.maybe_inline_local(
                         item.hir_id,
                         path.res,
@@ -280,7 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 }
 
                 om.imports.push(Import {
-                    name: ident.name,
+                    name,
                     id: item.hir_id,
                     vis: &item.vis,
                     attrs: &item.attrs,
@@ -296,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     &item.vis,
                     item.hir_id,
                     m,
-                    Some(ident.name),
+                    Some(name),
                 ));
             }
             hir::ItemKind::Fn(..)
@@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
-                if ident.name != kw::Underscore {
+                if name != kw::Underscore {
                     om.items.push((item, renamed));
                 }
             }
@@ -329,7 +329,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     fn visit_foreign_item(
         &mut self,
         item: &'tcx hir::ForeignItem<'_>,
-        renamed: Option<Ident>,
+        renamed: Option<Symbol>,
         om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
diff --git a/src/test/rustdoc-js/basic.rs b/src/test/rustdoc-js/basic.rs
index 1b4963fcebe..da946a58b1c 100644
--- a/src/test/rustdoc-js/basic.rs
+++ b/src/test/rustdoc-js/basic.rs
@@ -1,2 +1,2 @@
-/// Foo
+/// Docs for Foo
 pub struct Foo;
diff --git a/src/test/rustdoc-js/summaries.js b/src/test/rustdoc-js/summaries.js
new file mode 100644
index 00000000000..f175e47342d
--- /dev/null
+++ b/src/test/rustdoc-js/summaries.js
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2'];
+
+const EXPECTED = [
+    {
+        'others': [
+           { 'path': '', 'name': 'summaries', 'desc': 'This <em>summary</em> has a link and <code>code</code>.' },
+        ],
+    },
+    {
+        'others': [
+            { 'path': 'summaries', 'name': 'Sidebar', 'desc': 'This <code>code</code> will be rendered in a code tag.' },
+        ],
+    },
+    {
+        'others': [
+            { 'path': 'summaries', 'name': 'Sidebar2', 'desc': '' },
+        ],
+    },
+];
diff --git a/src/test/rustdoc-js/summaries.rs b/src/test/rustdoc-js/summaries.rs
new file mode 100644
index 00000000000..beb91e286b6
--- /dev/null
+++ b/src/test/rustdoc-js/summaries.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![crate_name = "summaries"]
+
+//! This *summary* has a [link] and `code`.
+//!
+//! This is the second paragraph.
+//!
+//! [link]: https://example.com
+
+/// This `code` will be rendered in a code tag.
+///
+/// This text should not be rendered.
+pub struct Sidebar;
+
+/// ```text
+/// this block should not be rendered
+/// ```
+pub struct Sidebar2;
diff --git a/src/test/rustdoc/intra-doc/raw-ident-self.rs b/src/test/rustdoc/intra-doc/raw-ident-self.rs
new file mode 100644
index 00000000000..d289797f146
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/raw-ident-self.rs
@@ -0,0 +1,13 @@
+#![deny(broken_intra_doc_links)]
+pub mod r#impl {
+    pub struct S;
+
+    impl S {
+        /// See [Self::b].
+        // @has raw_ident_self/impl/struct.S.html
+        // @has - '//a[@href="../../raw_ident_self/impl/struct.S.html#method.b"]' 'Self::b'
+        pub fn a() {}
+
+        pub fn b() {}
+    }
+}
diff --git a/src/test/rustdoc/plain-text-summaries.rs b/src/test/rustdoc/markdown-summaries.rs
index c995ccbf0af..b843e28e7b0 100644
--- a/src/test/rustdoc/plain-text-summaries.rs
+++ b/src/test/rustdoc/markdown-summaries.rs
@@ -1,21 +1,22 @@
 #![crate_type = "lib"]
 #![crate_name = "summaries"]
 
-//! This summary has a [link] and `code`.
+//! This *summary* has a [link] and `code`.
 //!
 //! This is the second paragraph.
 //!
 //! [link]: https://example.com
 
-// @has search-index.js 'This summary has a link and `code`.'
+// @has search-index.js 'This <em>summary</em> has a link and <code>code</code>.'
 // @!has - 'second paragraph'
 
-/// This `code` should be in backticks.
+/// This `code` will be rendered in a code tag.
 ///
 /// This text should not be rendered.
 pub struct Sidebar;
 
-// @has summaries/sidebar-items.js 'This `code` should be in backticks.'
+// @has search-index.js 'This <code>code</code> will be rendered in a code tag.'
+// @has summaries/sidebar-items.js 'This `code` will be rendered in a code tag.'
 // @!has - 'text should not be rendered'
 
 /// ```text
diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs
new file mode 100644
index 00000000000..053712a4b4e
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+#![feature(doc_keyword)]
+
+#![crate_type = "lib"]
+
+#![deny(rustc::existing_doc_keyword)]
+
+#[doc(keyword = "tadam")] //~ ERROR
+mod tadam {}
diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr
new file mode 100644
index 00000000000..bac44f338b7
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr
@@ -0,0 +1,15 @@
+error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]`
+  --> $DIR/existing_doc_keyword.rs:10:1
+   |
+LL | #[doc(keyword = "tadam")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/existing_doc_keyword.rs:8:9
+   |
+LL | #![deny(rustc::existing_doc_keyword)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: only existing keywords are allowed in core/std
+
+error: aborting due to previous error
+
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6
+Subproject 63d0fe43449adcb316d34d98a982b597faca417