From 1244ced9580b942926afc06815e0691cf3f4a846 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 27 Feb 2020 14:33:58 +0100
Subject: [PATCH 01/34] Remove "important traits" feature

---
 src/doc/rustdoc/src/unstable-features.md      | 21 ----
 .../src/language-features/doc-spotlight.md    | 30 ------
 src/librustc_feature/active.rs                |  3 -
 src/librustdoc/clean/inline.rs                |  2 -
 src/librustdoc/clean/mod.rs                   |  2 -
 src/librustdoc/clean/types.rs                 |  1 -
 src/librustdoc/html/format.rs                 | 12 ---
 src/librustdoc/html/render.rs                 | 85 +---------------
 src/librustdoc/html/static/main.js            | 28 ------
 src/librustdoc/html/static/rustdoc.css        | 96 +------------------
 src/librustdoc/html/static/themes/dark.css    | 33 -------
 src/librustdoc/html/static/themes/light.css   | 33 -------
 src/test/rustdoc/doc-spotlight.rs             | 36 -------
 .../feature-gate-doc_spotlight.rs             |  4 -
 .../feature-gate-doc_spotlight.stderr         | 12 ---
 15 files changed, 7 insertions(+), 391 deletions(-)
 delete mode 100644 src/doc/unstable-book/src/language-features/doc-spotlight.md
 delete mode 100644 src/test/rustdoc/doc-spotlight.rs
 delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
 delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr

diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index a48526d39fd0a..cf0280b6ff48c 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -138,27 +138,6 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
 [unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
 [issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
 
-### Adding your trait to the "Important Traits" dialog
-
-Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
-implemented on it. These traits are intended to be the primary interface for their types, and are
-often the only thing available to be documented on their types. For this reason, Rustdoc will track
-when a given type implements one of these traits and call special attention to it when a function
-returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
-to the function, which, when clicked, shows the dialog.
-
-In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
-`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
-special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
-attribute to your own trait to include it in the "Important Traits" dialog in documentation.
-
-The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
-For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
-issue][issue-spotlight].
-
-[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
-[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
-
 ### Exclude certain dependencies from documentation
 
 The standard library uses several dependencies which, in turn, use several types and traits from the
diff --git a/src/doc/unstable-book/src/language-features/doc-spotlight.md b/src/doc/unstable-book/src/language-features/doc-spotlight.md
deleted file mode 100644
index 8117755fef1c8..0000000000000
--- a/src/doc/unstable-book/src/language-features/doc-spotlight.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# `doc_spotlight`
-
-The tracking issue for this feature is: [#45040]
-
-The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
-to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
-attribute to a trait definition will make rustdoc print extra information for functions which return
-a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
-`io::Write` traits in the standard library.
-
-You can do this on your own traits, like this:
-
-```
-#![feature(doc_spotlight)]
-
-#[doc(spotlight)]
-pub trait MyTrait {}
-
-pub struct MyStruct;
-impl MyTrait for MyStruct {}
-
-/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
-/// without having to write that yourself!
-pub fn my_fn() -> MyStruct { MyStruct }
-```
-
-This feature was originally implemented in PR [#45039].
-
-[#45040]: https://github.com/rust-lang/rust/issues/45040
-[#45039]: https://github.com/rust-lang/rust/pull/45039
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 0082f4f1a6e89..1ca3b66580cd1 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -363,9 +363,6 @@ declare_features! (
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
-    /// Allows `#[doc(spotlight)]`.
-    (active, doc_spotlight, "1.22.0", Some(45040), None),
-
     /// Allows `#[doc(include = "some-file")]`.
     (active, external_doc, "1.22.0", Some(44732), None),
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 78222d21b934a..33ee6ffef0ebd 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -198,7 +198,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
     let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
-    let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
     let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         auto: auto_trait,
@@ -206,7 +205,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
-        is_spotlight,
         is_auto,
     }
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index af81087b53ed6..e1406e1637660 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1013,7 +1013,6 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
 impl Clean<Item> for doctree::Trait<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let attrs = self.attrs.clean(cx);
-        let is_spotlight = attrs.has_doc_flag(sym::spotlight);
         Item {
             name: Some(self.name.clean(cx)),
             attrs,
@@ -1028,7 +1027,6 @@ impl Clean<Item> for doctree::Trait<'_> {
                 items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
-                is_spotlight,
                 is_auto: self.is_auto.clean(cx),
             }),
         }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2f220cbc9be8c..ac868afbb6f1c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -952,7 +952,6 @@ pub struct Trait {
     pub items: Vec<Item>,
     pub generics: Generics,
     pub bounds: Vec<GenericBound>,
-    pub is_spotlight: bool,
     pub is_auto: bool,
 }
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index ec615fc858976..e60ff37fd279a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -63,22 +63,10 @@ impl Buffer {
         Buffer { for_html: false, buffer: String::new() }
     }
 
-    crate fn is_empty(&self) -> bool {
-        self.buffer.is_empty()
-    }
-
     crate fn into_inner(self) -> String {
         self.buffer
     }
 
-    crate fn insert_str(&mut self, idx: usize, s: &str) {
-        self.buffer.insert_str(idx, s);
-    }
-
-    crate fn push_str(&mut self, s: &str) {
-        self.buffer.push_str(s);
-    }
-
     // Intended for consumption by write! and writeln! (std::fmt) but without
     // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
     // import).
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 6a23b230e1224..8e2d593c730ee 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2324,7 +2324,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
         f.generics.print()
     )
     .len();
-    write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
+    write!(w, "<pre class='rust fn'>");
     render_attributes(w, it, false);
     write!(
         w,
@@ -2527,13 +2527,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-        write!(
-            w,
-            "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
-            extra = render_spotlight_traits(m),
-            id = id,
-            ns_id = ns_id
-        );
+        write!(w, "<h3 id='{id}' class='method'><code id='{ns_id}'>", id = id, ns_id = ns_id);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
@@ -3519,76 +3513,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
     }
 }
 
-fn render_spotlight_traits(item: &clean::Item) -> String {
-    match item.inner {
-        clean::FunctionItem(clean::Function { ref decl, .. })
-        | clean::TyMethodItem(clean::TyMethod { ref decl, .. })
-        | clean::MethodItem(clean::Method { ref decl, .. })
-        | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
-        _ => String::new(),
-    }
-}
-
-fn spotlight_decl(decl: &clean::FnDecl) -> String {
-    let mut out = Buffer::html();
-    let mut trait_ = String::new();
-
-    if let Some(did) = decl.output.def_id() {
-        let c = cache();
-        if let Some(impls) = c.impls.get(&did) {
-            for i in impls {
-                let impl_ = i.inner_impl();
-                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
-                    if out.is_empty() {
-                        out.push_str(&format!(
-                            "<h3 class=\"important\">Important traits for {}</h3>\
-                                      <code class=\"content\">",
-                            impl_.for_.print()
-                        ));
-                        trait_.push_str(&impl_.for_.print().to_string());
-                    }
-
-                    //use the "where" class here to make it small
-                    out.push_str(&format!(
-                        "<span class=\"where fmt-newline\">{}</span>",
-                        impl_.print()
-                    ));
-                    let t_did = impl_.trait_.def_id().unwrap();
-                    for it in &impl_.items {
-                        if let clean::TypedefItem(ref tydef, _) = it.inner {
-                            out.push_str("<span class=\"where fmt-newline\">    ");
-                            assoc_type(
-                                &mut out,
-                                it,
-                                &[],
-                                Some(&tydef.type_),
-                                AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
-                                "",
-                            );
-                            out.push_str(";</span>");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    if !out.is_empty() {
-        out.insert_str(
-            0,
-            &format!(
-                "<div class=\"important-traits\"><div class='tooltip'>ⓘ\
-                                    <span class='tooltiptext'>Important traits for {}</span></div>\
-                                    <div class=\"content hidden\">",
-                trait_
-            ),
-        );
-        out.push_str("</code></div></div>");
-    }
-
-    out.into_inner()
-}
-
 fn render_impl(
     w: &mut Buffer,
     cx: &Context,
@@ -3695,14 +3619,13 @@ fn render_impl(
                 (true, " hidden")
             };
         match item.inner {
-            clean::MethodItem(clean::Method { ref decl, .. })
-            | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
+            clean::MethodItem(clean::Method { .. })
+            | clean::TyMethodItem(clean::TyMethod { .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                     write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
-                    write!(w, "{}", spotlight_decl(decl));
                     write!(w, "<code id='{}'>", ns_id);
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 2870c6e0a6147..a799aed698578 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -341,7 +341,6 @@ function getSearchElement() {
     function handleEscape(ev) {
         var help = getHelpElement();
         var search = getSearchElement();
-        hideModal();
         if (hasClass(help, "hidden") === false) {
             displayHelp(false, ev, help);
         } else if (hasClass(search, "hidden") === false) {
@@ -373,7 +372,6 @@ function getSearchElement() {
             case "s":
             case "S":
                 displayHelp(false, ev);
-                hideModal();
                 ev.preventDefault();
                 focusSearchBar();
                 break;
@@ -386,7 +384,6 @@ function getSearchElement() {
 
             case "?":
                 if (ev.shiftKey) {
-                    hideModal();
                     displayHelp(true, ev);
                 }
                 break;
@@ -2504,31 +2501,6 @@ function getSearchElement() {
         lineNumbersFunc(e);
     });
 
-    function showModal(content) {
-        var modal = document.createElement("div");
-        modal.id = "important";
-        addClass(modal, "modal");
-        modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
-                          "</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
-                          "</span></div>";
-        document.getElementsByTagName("body")[0].appendChild(modal);
-        document.getElementById("modal-close").onclick = hideModal;
-        modal.onclick = hideModal;
-    }
-
-    function hideModal() {
-        var modal = document.getElementById("important");
-        if (modal) {
-            modal.parentNode.removeChild(modal);
-        }
-    }
-
-    onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
-        e.onclick = function() {
-            showModal(e.lastElementChild.innerHTML);
-        };
-    });
-
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
         if (nb === 0 || nb === 1 || nb === 2) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 0dfe82c501469..f05db6c218524 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -143,12 +143,9 @@ code, pre, a.test-arrow {
 	border-radius: 3px;
 	padding: 0 0.1em;
 }
-.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
+.docblock pre code, .docblock-short pre code {
 	padding: 0;
 }
-.docblock code.spotlight :last-child {
-	padding-bottom: 0.6em;
-}
 pre {
 	padding: 14px;
 }
@@ -503,7 +500,7 @@ h4 > code, h3 > code, .invisible > code {
 	font-size: 0.8em;
 }
 
-.content .methods > div:not(.important-traits) {
+.content .methods > div {
 	margin-left: 40px;
 	margin-bottom: 15px;
 }
@@ -1072,7 +1069,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	border-style: solid;
 }
 
-.important-traits .tooltip .tooltiptext {
+.tooltip .tooltiptext {
 	border: 1px solid;
 }
 
@@ -1117,17 +1114,6 @@ pre.rust {
 	font-size: 16px;
 }
 
-.important-traits {
-	cursor: pointer;
-	z-index: 2;
-}
-
-h4 > .important-traits {
-	position: absolute;
-	left: -44px;
-	top: 2px;
-}
-
 #all-types {
 	text-align: center;
 	border: 1px solid;
@@ -1354,12 +1340,6 @@ h4 > .important-traits {
 		z-index: 1;
 	}
 
-	h4 > .important-traits {
-		position: absolute;
-		left: -22px;
-		top: 24px;
-	}
-
 	#titles > div > div.count {
 		float: left;
 		width: 100%;
@@ -1462,82 +1442,12 @@ h4 > .important-traits {
 	}
 }
 
-.modal {
-	position: fixed;
-	width: 100vw;
-	height: 100vh;
-	z-index: 10000;
-	top: 0;
-	left: 0;
-}
-
-.modal-content {
-	display: block;
-	max-width: 60%;
-	min-width: 200px;
-	padding: 8px;
-	top: 40%;
-	position: absolute;
-	left: 50%;
-	transform: translate(-50%, -40%);
-	border: 1px solid;
-	border-radius: 4px;
-	border-top-right-radius: 0;
-}
-
-.modal-content > .docblock {
-	margin: 0;
-}
-
 h3.important {
 	margin: 0;
 	margin-bottom: 13px;
 	font-size: 19px;
 }
 
-.modal-content > .docblock > code.content {
-	margin: 0;
-	padding: 0;
-	font-size: 20px;
-}
-
-.modal-content > .close {
-	position: absolute;
-	font-weight: 900;
-	right: -25px;
-	top: -1px;
-	font-size: 18px;
-	width: 25px;
-	padding-right: 2px;
-	border-top-right-radius: 5px;
-	border-bottom-right-radius: 5px;
-	text-align: center;
-	border: 1px solid;
-	border-right: 0;
-	cursor: pointer;
-}
-
-.modal-content > .whiter {
-	height: 25px;
-	position: absolute;
-	width: 3px;
-	right: -2px;
-	top: 0px;
-}
-
-#main > div.important-traits {
-	position: absolute;
-	left: -24px;
-	margin-top: 16px;
-}
-
-.content > .methods > .method > div.important-traits {
-	position: absolute;
-	font-weight: 400;
-	left: -42px;
-	margin-top: 2px;
-}
-
 kbd {
 	display: inline-block;
 	padding: 3px 5px;
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 9a0e7bbabcba9..e7041d54c6bfd 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -298,12 +298,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
-.important-traits .tooltip .tooltiptext {
-	background-color: white;
-	color: black;
-	border-color: black;
-}
-
 #titles > div:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
@@ -317,33 +311,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: #888;
 }
 
-.modal {
-	background-color: rgba(0,0,0,0.3);
-}
-
-.modal-content {
-	background-color: #272727;
-	border-color: #999;
-}
-
-.modal-content > .close {
-	background-color: #272727;
-	border-color: #999;
-}
-
-.modal-content > .close:hover {
-	background-color: #ff1f1f;
-	color: white;
-}
-
-.modal-content > .whiter {
-	background-color: #272727;
-}
-
-.modal-content > .close:hover + .whiter {
-	background-color: #ff1f1f;
-}
-
 @media (max-width: 700px) {
 	.sidebar-menu {
 		background-color: #505050;
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index ca8ea1c456a2c..a1efef6701fd1 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -292,12 +292,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
-.important-traits .tooltip .tooltiptext {
-	background-color: white;
-	color: black;
-	border-color: black;
-}
-
 #titles > div:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;
@@ -311,33 +305,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: #888;
 }
 
-.modal {
-	background-color: rgba(0,0,0,0.3);
-}
-
-.modal-content {
-	background-color: #eee;
-	border-color: #999;
-}
-
-.modal-content > .close {
-	background-color: #eee;
-	border-color: #999;
-}
-
-.modal-content > .close:hover {
-	background-color: #ff1f1f;
-	color: white;
-}
-
-.modal-content > .whiter {
-	background-color: #eee;
-}
-
-.modal-content > .close:hover + .whiter {
-	background-color: #ff1f1f;
-}
-
 @media (max-width: 700px) {
 	.sidebar-menu {
 		background-color: #F1F1F1;
diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-spotlight.rs
deleted file mode 100644
index ddd46c3c2155f..0000000000000
--- a/src/test/rustdoc/doc-spotlight.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-#![feature(doc_spotlight)]
-
-pub struct Wrapper<T> {
-    inner: T,
-}
-
-impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
-
-#[doc(spotlight)]
-pub trait SomeTrait {
-    // @has doc_spotlight/trait.SomeTrait.html
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
-    fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
-        Wrapper {
-            inner: self,
-        }
-    }
-}
-
-pub struct SomeStruct;
-impl SomeTrait for SomeStruct {}
-
-impl SomeStruct {
-    // @has doc_spotlight/struct.SomeStruct.html
-    // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
-    pub fn new() -> SomeStruct {
-        SomeStruct
-    }
-}
-
-// @has doc_spotlight/fn.bare_fn.html
-// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
-pub fn bare_fn() -> SomeStruct {
-    SomeStruct
-}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
deleted file mode 100644
index 452b45b34456b..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
-trait SomeTrait {}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
deleted file mode 100644
index 010d74054a412..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: `#[doc(spotlight)]` is experimental
-  --> $DIR/feature-gate-doc_spotlight.rs:1:1
-   |
-LL | #[doc(spotlight)]
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
-   = help: add `#![feature(doc_spotlight)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.

From 13c6d5819aae3c0de6a90e7f17ea967bf4487cbb Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Thu, 27 Feb 2020 14:38:30 +0100
Subject: [PATCH 02/34] Remove spotlight usage

---
 src/libcore/future/future.rs            | 1 -
 src/libcore/iter/traits/iterator.rs     | 1 -
 src/libcore/lib.rs                      | 1 -
 src/librustc_ast_passes/feature_gate.rs | 1 -
 src/librustc_span/symbol.rs             | 2 --
 src/libstd/io/mod.rs                    | 2 --
 src/libstd/lib.rs                       | 1 -
 7 files changed, 9 deletions(-)

diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index f14ed38b9b0f2..00a171e6b5fb1 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -24,7 +24,6 @@ use crate::task::{Context, Poll};
 /// `.await` the value.
 ///
 /// [`Waker`]: ../task/struct.Waker.html
-#[doc(spotlight)]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[lang = "future_trait"]
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index 1d055676c7708..83c9a5fbe15ef 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -92,7 +92,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
     label = "`{Self}` is not an iterator",
     message = "`{Self}` is not an iterator"
 )]
-#[doc(spotlight)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 pub trait Iterator {
     /// The type of the elements being iterated over.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index bca96b77812c8..21806fad8ff1b 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -90,7 +90,6 @@
 #![feature(custom_inner_attributes)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
-#![feature(doc_spotlight)]
 #![feature(extern_types)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 3c924847a7364..2146eec338f71 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -245,7 +245,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     include => external_doc
                     cfg => doc_cfg
                     masked => doc_masked
-                    spotlight => doc_spotlight
                     alias => doc_alias
                     keyword => doc_keyword
                 );
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 97708d91d7e2a..42e92b60d69f5 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -269,7 +269,6 @@ symbols! {
         doc_cfg,
         doc_keyword,
         doc_masked,
-        doc_spotlight,
         doctest,
         document_private_items,
         dotdoteq_in_patterns,
@@ -688,7 +687,6 @@ symbols! {
         Some,
         specialization,
         speed,
-        spotlight,
         sse4a_target_feature,
         stable,
         staged_api,
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 67b382c7a845e..1f88a6a5576b6 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -497,7 +497,6 @@ where
 /// [`&str`]: ../../std/primitive.str.html
 /// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
 pub trait Read {
     /// Pull some bytes from this source into the specified buffer, returning
     /// how many bytes were read.
@@ -1228,7 +1227,6 @@ impl Initializer {
 ///
 /// [`write_all`]: #method.write_all
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(spotlight)]
 pub trait Write {
     /// Write a buffer into this writer, returning how many bytes were written.
     ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 799585ffc0acf..f482eb6b2eee5 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -256,7 +256,6 @@
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
 #![feature(doc_masked)]
-#![feature(doc_spotlight)]
 #![feature(dropck_eyepatch)]
 #![feature(duration_constants)]
 #![feature(exact_size_is_empty)]

From 7859f0eac3b70fea1f129665d0b9f4c56769fa4c Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 2 Mar 2020 21:47:33 -0300
Subject: [PATCH 03/34] Make PlaceRef lifetimes of Place::as_ref be both 'tcx

---
 src/librustc/mir/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 668240ab42b4c..0d429d8879bac 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1864,7 +1864,7 @@ impl<'tcx> Place<'tcx> {
         self.as_ref().as_local()
     }
 
-    pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
+    pub fn as_ref(&self) -> PlaceRef<'tcx, 'tcx> {
         PlaceRef { local: self.local, projection: &self.projection }
     }
 }

From 812e62f14609fe80c49664f8b4ee5678c126c4a3 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 2 Mar 2020 22:02:52 -0300
Subject: [PATCH 04/34] Make PlaceRef lifetimes of LocalAnalyzer::process_place
 be both 'tcx

---
 src/librustc_codegen_ssa/mir/analyze.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 7bf222f4701b7..6214aa84b81d6 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -97,7 +97,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
 
     fn process_place(
         &mut self,
-        place_ref: &mir::PlaceRef<'_, 'tcx>,
+        place_ref: &mir::PlaceRef<'tcx, 'tcx>,
         context: PlaceContext,
         location: Location,
     ) {

From 1a1dcfad6fa13f1b2b69b0e111dcad10326d36ea Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 3 Mar 2020 16:55:01 -0300
Subject: [PATCH 05/34] Make PlaceRef lifetimes of codegen_place be both 'tcx

---
 src/librustc_codegen_ssa/mir/operand.rs | 4 ++--
 src/librustc_codegen_ssa/mir/place.rs   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index af95450935caa..96c1351de410c 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn maybe_codegen_consume_direct(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx, 'tcx>,
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
@@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_consume(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx, 'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
         debug!("codegen_consume(place_ref={:?})", place_ref);
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index fa82daa0f7d52..0d2749d3f5feb 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_place(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'_, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx, 'tcx>,
     ) -> PlaceRef<'tcx, Bx::Value> {
         debug!("codegen_place(place_ref={:?})", place_ref);
         let cx = self.cx;

From 2af5e87b4b3ef9c7210e4b40ad86a14ff32932f1 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 3 Mar 2020 17:00:57 -0300
Subject: [PATCH 06/34] Make PlaceRef lifetimes of monomorphized_place_ty be
 both 'tcx

---
 src/librustc_codegen_ssa/mir/place.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 0d2749d3f5feb..3ff0c8dd2aa46 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         result
     }
 
-    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
+    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx, 'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
         let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
         self.monomorphize(&place_ty.ty)

From a20d54f00cb4b5386e1b307bc1c990eac02184da Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 3 Mar 2020 17:22:54 -0300
Subject: [PATCH 07/34] Make PlaceRef lifetimes of RootPlace be both 'tcx

---
 src/librustc_mir/borrow_check/mod.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 28974dcd08bf6..4e21ba86d0996 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -841,9 +841,9 @@ enum InitializationRequiringAction {
     PartialAssignment,
 }
 
-struct RootPlace<'d, 'tcx> {
+struct RootPlace<'tcx> {
     place_local: Local,
-    place_projection: &'d [PlaceElem<'tcx>],
+    place_projection: &'tcx [PlaceElem<'tcx>],
     is_local_mutation_allowed: LocalMutationIsAllowed,
 }
 
@@ -2029,7 +2029,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// Adds the place into the used mutable variables set
-    fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
+    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
         match root_place {
             RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
@@ -2063,11 +2063,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// Whether this value can be written or borrowed mutably.
     /// Returns the root place if the place passed in is a projection.
-    fn is_mutable<'d>(
+    fn is_mutable(
         &self,
-        place: PlaceRef<'d, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-    ) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
+    ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx, 'tcx>> {
         match place {
             PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[local];

From 842af362685979e011e0360984dc1ec96ba5b7e9 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 11:21:01 -0300
Subject: [PATCH 08/34] Make PlaceRef lifetimes of borrow_conflict_place be
 both 'tcx

---
 src/librustc_mir/borrow_check/mod.rs             | 5 +++--
 src/librustc_mir/borrow_check/places_conflict.rs | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4e21ba86d0996..84c9f733be058 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -86,6 +86,8 @@ crate struct Upvar {
     mutability: Mutability,
 }
 
+const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref];
+
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers { mir_borrowck, ..*providers };
 }
@@ -1413,7 +1415,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
-        let deref = [ProjectionElem::Deref];
         let mut root_place = PlaceRef { local: place.local, projection: &[] };
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
@@ -1427,7 +1428,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // Thread-locals might be dropped after the function exits
                 // We have to dereference the outer reference because
                 // borrows don't conflict behind shared references.
-                root_place.projection = &deref;
+                root_place.projection = DEREF_PROJECTION;
                 (true, true)
             } else {
                 (false, self.locals_are_invalidated_at_exit)
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 984de021ca112..1f90b94cfcdc3 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'_, 'tcx>,
+    access_place: PlaceRef<'tcx, 'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
@@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'_, 'tcx>,
+    access_place: PlaceRef<'tcx, 'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {

From f54e8634e1394d3436037ff54e0f87739709a916 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 13:00:08 -0300
Subject: [PATCH 09/34] Make PlaceRef lifetimes of move_error_reported be both
 'tcx

---
 .../borrow_check/diagnostics/conflict_errors.rs       |  2 +-
 src/librustc_mir/borrow_check/mod.rs                  | 11 ++++++-----
 src/librustc_mir/borrow_check/prefixes.rs             |  6 +++---
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index ca51d16f9f269..9d609411a54bb 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
+        (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span),
         mpi: MovePathIndex,
     ) {
         debug!(
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 84c9f733be058..2d73d96ec8b6a 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -468,7 +468,8 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
     /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
     /// when errors in the map are being re-added to the error buffer so that errors with the
     /// same primary span come out in a consistent order.
-    move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'cx, 'tcx>, DiagnosticBuilder<'cx>)>,
+    move_error_reported:
+        BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>,
     /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
     uninitialized_error_reported: FxHashSet<PlaceRef<'cx, 'tcx>>,
@@ -1527,7 +1528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx, 'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1593,7 +1594,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx, 'tcx>, Span),
         maybe_uninits: &BitSet<MovePathIndex>,
         from: u32,
         to: u32,
@@ -1632,7 +1633,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'cx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx, 'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1817,7 +1818,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         fn check_parent_of_field<'cx, 'tcx>(
             this: &mut MirBorrowckCtxt<'cx, 'tcx>,
             location: Location,
-            base: PlaceRef<'cx, 'tcx>,
+            base: PlaceRef<'tcx, 'tcx>,
             span: Span,
             flow_state: &Flows<'cx, 'tcx>,
         ) {
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 31bee460fa011..b66fd42d9c024 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
     body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: PrefixSet,
-    next: Option<PlaceRef<'cx, 'tcx>>,
+    next: Option<PlaceRef<'tcx, 'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// terminating the iteration early based on `kind`.
     pub(super) fn prefixes(
         &self,
-        place_ref: PlaceRef<'cx, 'tcx>,
+        place_ref: PlaceRef<'tcx, 'tcx>,
         kind: PrefixSet,
     ) -> Prefixes<'cx, 'tcx> {
         Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
@@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
-    type Item = PlaceRef<'cx, 'tcx>;
+    type Item = PlaceRef<'tcx, 'tcx>;
     fn next(&mut self) -> Option<Self::Item> {
         let mut cursor = self.next?;
 

From 6200f5c362172431279cd4feed4bd20beb7e2c7e Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 13:09:32 -0300
Subject: [PATCH 10/34] Make PlaceRef lifetimes of uninitialized_error_reported
 be both 'tcx

---
 src/librustc_mir/borrow_check/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 2d73d96ec8b6a..fb3338f998d4a 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -472,7 +472,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
         BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>,
     /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
-    uninitialized_error_reported: FxHashSet<PlaceRef<'cx, 'tcx>>,
+    uninitialized_error_reported: FxHashSet<PlaceRef<'tcx, 'tcx>>,
     /// Errors to be reported buffer
     errors_buffer: Vec<Diagnostic>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.

From e32ee55a365712ef2cca97c0e37a8e56efecafd2 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 14:02:11 -0300
Subject: [PATCH 11/34] Make PlaceRef lifetimes of move_path_closest_to be both
 'tcx

---
 src/librustc_mir/borrow_check/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index fb3338f998d4a..49c499fb62dbd 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1713,8 +1713,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// static variable, as we do not track those in the MoveData.
     fn move_path_closest_to(
         &mut self,
-        place: PlaceRef<'_, 'tcx>,
-    ) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) {
+        place: PlaceRef<'tcx, 'tcx>,
+    ) -> (PlaceRef<'tcx, 'tcx>, MovePathIndex) {
         match self.move_data.rev_lookup.find(place) {
             LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
                 (self.move_data.move_paths[mpi].place.as_ref(), mpi)

From 634a167e0594330fb50bf9bd742fdafeb73ed963 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 14:06:20 -0300
Subject: [PATCH 12/34] Make PlaceRef lifetimes of move_path_for_place be both
 'tcx

---
 src/librustc_mir/borrow_check/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 49c499fb62dbd..77129a5ef9e79 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1723,7 +1723,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
-    fn move_path_for_place(&mut self, place: PlaceRef<'_, 'tcx>) -> Option<MovePathIndex> {
+    fn move_path_for_place(&mut self, place: PlaceRef<'tcx, 'tcx>) -> Option<MovePathIndex> {
         // If returns None, then there is no move path corresponding
         // to a direct owner of `place` (which means there is nothing
         // that borrowck tracks for its analysis).

From c6f12447193d3710a38ad2e069605fe1cc2847ba Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 17:00:15 -0300
Subject: [PATCH 13/34] Make PlaceRef lifetimes of is_upvar_field_projection be
 both 'tcx

---
 .../borrow_check/diagnostics/conflict_errors.rs             | 4 ++--
 src/librustc_mir/borrow_check/diagnostics/mod.rs            | 6 +++---
 src/librustc_mir/borrow_check/mod.rs                        | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 9d609411a54bb..3a74353605294 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span),
+        (moved_place, used_place, span): (PlaceRef<'tcx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span),
         mpi: MovePathIndex,
     ) {
         debug!(
@@ -647,7 +647,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // borrowed place and look for a access to a different field of the same union.
                 let Place { local, projection } = second_borrowed_place;
 
-                let mut cursor = projection.as_ref();
+                let mut cursor = &projection[..];
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index cd6834a5a4d00..01c022ac2c10f 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -139,7 +139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// End-user visible description of `place` if one can be found. If the
     /// place is a temporary for instance, None will be returned.
-    pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<String> {
+    pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option<String> {
         self.describe_place_with_options(place_ref, IncludingDowncast(false))
     }
 
@@ -149,7 +149,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// `Downcast` and `IncludingDowncast` is true
     pub(super) fn describe_place_with_options(
         &self,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
         including_downcast: IncludingDowncast,
     ) -> Option<String> {
         let mut buf = String::new();
@@ -162,7 +162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Appends end-user visible description of `place` to `buf`.
     fn append_place_to_string(
         &self,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
         buf: &mut String,
         mut autoderef: bool,
         including_downcast: &IncludingDowncast,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 77129a5ef9e79..89a81945a27b3 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -2220,7 +2220,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// then returns the index of the field being projected. Note that this closure will always
     /// be `self` in the current MIR, because that is the only time we directly access the fields
     /// of a closure type.
-    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<Field> {
+    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option<Field> {
         let mut place_projection = place_ref.projection;
         let mut by_ref = false;
 

From 6f236504570de4210eeae6e883cf8ed6196e0d98 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 17:12:31 -0300
Subject: [PATCH 14/34] Make PlaceRef lifetimes of
 add_moved_or_invoked_closure_note be both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index 01c022ac2c10f..ed95c0419e9bd 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(super) fn add_moved_or_invoked_closure_note(
         &self,
         location: Location,
-        place: PlaceRef<'cx, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);

From eb67eca74af8765dc4f5579655783b51f0270b49 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 17:22:28 -0300
Subject: [PATCH 15/34] Make PlaceRef lifetimes of describe_field be both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index ed95c0419e9bd..2f054b8dd52d7 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -303,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// End-user visible description of the `field`nth field of `base`
-    fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
+    fn describe_field(&self, place: PlaceRef<'tcx, 'tcx>, field: Field) -> String {
         // FIXME Place2 Make this work iteratively
         match place {
             PlaceRef { local, projection: [] } => {

From a30f55f4b2fc71acd04f5649678ca09c1523096d Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 17:47:00 -0300
Subject: [PATCH 16/34] Make PlaceRef lifetimes of borrowed_content_source be
 both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/mod.rs               | 2 +-
 src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index 2f054b8dd52d7..e2d59ed3c6e87 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -399,7 +399,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     pub(super) fn borrowed_content_source(
         &self,
-        deref_base: PlaceRef<'cx, 'tcx>,
+        deref_base: PlaceRef<'tcx, 'tcx>,
     ) -> BorrowedContentSource<'tcx> {
         let tcx = self.infcx.tcx;
 
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index d91f6edc9800c..aa35c407b64e6 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -23,7 +23,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         &mut self,
         access_place: &Place<'tcx>,
         span: Span,
-        the_place_err: PlaceRef<'cx, 'tcx>,
+        the_place_err: PlaceRef<'tcx, 'tcx>,
         error_access: AccessKind,
         location: Location,
     ) {

From bd4dad4281220325dc5ae3ecca8c286ecba9b681 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:05:37 -0300
Subject: [PATCH 17/34] Make PlaceRef lifetimes of move_spans be both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index e2d59ed3c6e87..2565eeae06bc5 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
         &self,
-        moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar.
+        moved_place: PlaceRef<'tcx, 'tcx>, // Could also be an upvar.
         location: Location,
     ) -> UseSpans {
         use self::UseSpans::*;

From 46d85e519bcd2b64ca0b069055e880b425fb3e74 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:07:33 -0300
Subject: [PATCH 18/34] Make PlaceRef lifetimes of closure_span be both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index 2565eeae06bc5..4b1c0b05817de 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     fn closure_span(
         &self,
         def_id: DefId,
-        target_place: PlaceRef<'cx, 'tcx>,
+        target_place: PlaceRef<'tcx, 'tcx>,
         places: &Vec<Operand<'tcx>>,
     ) -> Option<(Span, Option<GeneratorKind>, Span)> {
         debug!(

From a32afa33c8a8ad58607bafbfb9399b2c51495e61 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:10:01 -0300
Subject: [PATCH 19/34] Make PlaceRef lifetimes of classify_drop_access_kind be
 both 'tcx

---
 src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 3a74353605294..99cbc76efab88 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err.buffer(&mut self.errors_buffer);
     }
 
-    fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
+    fn classify_drop_access_kind(&self, place: PlaceRef<'tcx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place.projection {
             [] => StorageDeadOrDrop::LocalStorageDead,

From a5d1e189a12433d61ded6da47df76929cf8e94c1 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:13:47 -0300
Subject: [PATCH 20/34] Make PlaceRef lifetimes of is_prefix_of be both 'tcx

---
 src/librustc_mir/borrow_check/prefixes.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index b66fd42d9c024..25356cd17ef18 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -13,12 +13,12 @@ use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
 use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 
-pub trait IsPrefixOf<'cx, 'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
+pub trait IsPrefixOf<'tcx> {
+    fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool;
 }
 
-impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
+impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx, 'tcx> {
+    fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool {
         self.local == other.local
             && self.projection.len() <= other.projection.len()
             && self.projection == &other.projection[..self.projection.len()]

From 2cb2559c18c2d494710ab67324cdc73c4be7a46f Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:18:15 -0300
Subject: [PATCH 21/34] Make PlaceRef lifetimes of in_projection be both 'tcx

---
 src/librustc_mir/dataflow/move_paths/builder.rs    | 2 +-
 src/librustc_mir/transform/check_consts/qualifs.rs | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 57aa5de7f7a31..fb7ae102a0f18 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -483,7 +483,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         self.builder.data.loc_map[self.loc].push(move_out);
     }
 
-    fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) {
+    fn gather_init(&mut self, place: PlaceRef<'tcx, 'tcx>, kind: InitKind) {
         debug!("gather_init({:?}, {:?})", self.loc, place);
 
         let mut place = place;
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 215496e4d03cb..275b6e4d508f0 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -35,7 +35,7 @@ pub trait Qualif {
     fn in_projection_structurally(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
     ) -> bool {
         if let [proj_base @ .., elem] = place.projection {
             let base_qualif = Self::in_place(
@@ -67,7 +67,7 @@ pub trait Qualif {
     fn in_projection(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
     ) -> bool {
         Self::in_projection_structurally(cx, per_local, place)
     }
@@ -75,7 +75,7 @@ pub trait Qualif {
     fn in_place(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'_, 'tcx>,
+        place: PlaceRef<'tcx, 'tcx>,
     ) -> bool {
         match place {
             PlaceRef { local, projection: [] } => per_local(local),

From b11cd0b587cc2a663ef358089a2d1cf709170371 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 4 Mar 2020 18:25:03 -0300
Subject: [PATCH 22/34] PlaceRef<'a, 'tcx> -> PlaceRef<'tcx>

---
 src/librustc/mir/mod.rs                       |  8 +++---
 src/librustc_codegen_ssa/mir/analyze.rs       |  2 +-
 src/librustc_codegen_ssa/mir/operand.rs       |  4 +--
 src/librustc_codegen_ssa/mir/place.rs         |  4 +--
 .../diagnostics/conflict_errors.rs            |  4 +--
 .../borrow_check/diagnostics/mod.rs           | 16 ++++++------
 .../diagnostics/mutability_errors.rs          |  2 +-
 src/librustc_mir/borrow_check/mod.rs          | 26 ++++++++-----------
 .../borrow_check/places_conflict.rs           |  4 +--
 src/librustc_mir/borrow_check/prefixes.rs     | 12 ++++-----
 .../dataflow/move_paths/builder.rs            |  2 +-
 src/librustc_mir/dataflow/move_paths/mod.rs   |  2 +-
 src/librustc_mir/transform/add_retag.rs       |  2 +-
 .../transform/check_consts/qualifs.rs         |  6 ++---
 src/librustc_mir/transform/promote_consts.rs  |  2 +-
 15 files changed, 46 insertions(+), 50 deletions(-)

diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 0d429d8879bac..ca97366f5146a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1827,9 +1827,9 @@ rustc_index::newtype_index! {
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct PlaceRef<'a, 'tcx> {
+pub struct PlaceRef<'tcx> {
     pub local: Local,
-    pub projection: &'a [PlaceElem<'tcx>],
+    pub projection: &'tcx [PlaceElem<'tcx>],
 }
 
 impl<'tcx> Place<'tcx> {
@@ -1864,7 +1864,7 @@ impl<'tcx> Place<'tcx> {
         self.as_ref().as_local()
     }
 
-    pub fn as_ref(&self) -> PlaceRef<'tcx, 'tcx> {
+    pub fn as_ref(&self) -> PlaceRef<'tcx> {
         PlaceRef { local: self.local, projection: &self.projection }
     }
 }
@@ -1875,7 +1875,7 @@ impl From<Local> for Place<'_> {
     }
 }
 
-impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
+impl<'tcx> PlaceRef<'tcx> {
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
     //
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 6214aa84b81d6..2f7e70901f0f3 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -97,7 +97,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
 
     fn process_place(
         &mut self,
-        place_ref: &mir::PlaceRef<'tcx, 'tcx>,
+        place_ref: &mir::PlaceRef<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 96c1351de410c..1e1fede2588df 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn maybe_codegen_consume_direct(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'tcx, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
@@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_consume(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'tcx, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
         debug!("codegen_consume(place_ref={:?})", place_ref);
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 3ff0c8dd2aa46..2eba88c6b5f31 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_place(
         &mut self,
         bx: &mut Bx,
-        place_ref: mir::PlaceRef<'tcx, 'tcx>,
+        place_ref: mir::PlaceRef<'tcx>,
     ) -> PlaceRef<'tcx, Bx::Value> {
         debug!("codegen_place(place_ref={:?})", place_ref);
         let cx = self.cx;
@@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         result
     }
 
-    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx, 'tcx>) -> Ty<'tcx> {
+    pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
         let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
         self.monomorphize(&place_ty.ty)
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 99cbc76efab88..6dc5d62babda6 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        (moved_place, used_place, span): (PlaceRef<'tcx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span),
+        (moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span),
         mpi: MovePathIndex,
     ) {
         debug!(
@@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err.buffer(&mut self.errors_buffer);
     }
 
-    fn classify_drop_access_kind(&self, place: PlaceRef<'tcx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
+    fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place.projection {
             [] => StorageDeadOrDrop::LocalStorageDead,
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index 4b1c0b05817de..912b5f11f1a04 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     pub(super) fn add_moved_or_invoked_closure_note(
         &self,
         location: Location,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
@@ -139,7 +139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// End-user visible description of `place` if one can be found. If the
     /// place is a temporary for instance, None will be returned.
-    pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option<String> {
+    pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> {
         self.describe_place_with_options(place_ref, IncludingDowncast(false))
     }
 
@@ -149,7 +149,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// `Downcast` and `IncludingDowncast` is true
     pub(super) fn describe_place_with_options(
         &self,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
         including_downcast: IncludingDowncast,
     ) -> Option<String> {
         let mut buf = String::new();
@@ -162,7 +162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Appends end-user visible description of `place` to `buf`.
     fn append_place_to_string(
         &self,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
         buf: &mut String,
         mut autoderef: bool,
         including_downcast: &IncludingDowncast,
@@ -303,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 
     /// End-user visible description of the `field`nth field of `base`
-    fn describe_field(&self, place: PlaceRef<'tcx, 'tcx>, field: Field) -> String {
+    fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
         // FIXME Place2 Make this work iteratively
         match place {
             PlaceRef { local, projection: [] } => {
@@ -399,7 +399,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     pub(super) fn borrowed_content_source(
         &self,
-        deref_base: PlaceRef<'tcx, 'tcx>,
+        deref_base: PlaceRef<'tcx>,
     ) -> BorrowedContentSource<'tcx> {
         let tcx = self.infcx.tcx;
 
@@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
         &self,
-        moved_place: PlaceRef<'tcx, 'tcx>, // Could also be an upvar.
+        moved_place: PlaceRef<'tcx>, // Could also be an upvar.
         location: Location,
     ) -> UseSpans {
         use self::UseSpans::*;
@@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     fn closure_span(
         &self,
         def_id: DefId,
-        target_place: PlaceRef<'tcx, 'tcx>,
+        target_place: PlaceRef<'tcx>,
         places: &Vec<Operand<'tcx>>,
     ) -> Option<(Span, Option<GeneratorKind>, Span)> {
         debug!(
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index aa35c407b64e6..1a13ef8958576 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -23,7 +23,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         &mut self,
         access_place: &Place<'tcx>,
         span: Span,
-        the_place_err: PlaceRef<'tcx, 'tcx>,
+        the_place_err: PlaceRef<'tcx>,
         error_access: AccessKind,
         location: Location,
     ) {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 89a81945a27b3..4e84a4169890e 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -468,11 +468,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
     /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
     /// when errors in the map are being re-added to the error buffer so that errors with the
     /// same primary span come out in a consistent order.
-    move_error_reported:
-        BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>,
+    move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'cx>)>,
     /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
-    uninitialized_error_reported: FxHashSet<PlaceRef<'tcx, 'tcx>>,
+    uninitialized_error_reported: FxHashSet<PlaceRef<'tcx>>,
     /// Errors to be reported buffer
     errors_buffer: Vec<Diagnostic>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
@@ -1528,7 +1527,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'tcx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1594,7 +1593,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'tcx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         maybe_uninits: &BitSet<MovePathIndex>,
         from: u32,
         to: u32,
@@ -1633,7 +1632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
-        place_span: (PlaceRef<'tcx, 'tcx>, Span),
+        place_span: (PlaceRef<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
@@ -1711,10 +1710,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// An Err result includes a tag indicated why the search failed.
     /// Currently this can only occur if the place is built off of a
     /// static variable, as we do not track those in the MoveData.
-    fn move_path_closest_to(
-        &mut self,
-        place: PlaceRef<'tcx, 'tcx>,
-    ) -> (PlaceRef<'tcx, 'tcx>, MovePathIndex) {
+    fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) {
         match self.move_data.rev_lookup.find(place) {
             LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
                 (self.move_data.move_paths[mpi].place.as_ref(), mpi)
@@ -1723,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
-    fn move_path_for_place(&mut self, place: PlaceRef<'tcx, 'tcx>) -> Option<MovePathIndex> {
+    fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option<MovePathIndex> {
         // If returns None, then there is no move path corresponding
         // to a direct owner of `place` (which means there is nothing
         // that borrowck tracks for its analysis).
@@ -1818,7 +1814,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         fn check_parent_of_field<'cx, 'tcx>(
             this: &mut MirBorrowckCtxt<'cx, 'tcx>,
             location: Location,
-            base: PlaceRef<'tcx, 'tcx>,
+            base: PlaceRef<'tcx>,
             span: Span,
             flow_state: &Flows<'cx, 'tcx>,
         ) {
@@ -2067,9 +2063,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Returns the root place if the place passed in is a projection.
     fn is_mutable(
         &self,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-    ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx, 'tcx>> {
+    ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
         match place {
             PlaceRef { local, projection: [] } => {
                 let local = &self.body.local_decls[local];
@@ -2220,7 +2216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// then returns the index of the field being projected. Note that this closure will always
     /// be `self` in the current MIR, because that is the only time we directly access the fields
     /// of a closure type.
-    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option<Field> {
+    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
         let mut place_projection = place_ref.projection;
         let mut by_ref = false;
 
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 1f90b94cfcdc3..767ffa50fedb4 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'tcx, 'tcx>,
+    access_place: PlaceRef<'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
@@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>(
     body: &Body<'tcx>,
     borrow_place: &Place<'tcx>,
     borrow_kind: BorrowKind,
-    access_place: PlaceRef<'tcx, 'tcx>,
+    access_place: PlaceRef<'tcx>,
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index 25356cd17ef18..c64e8c363af54 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -14,11 +14,11 @@ use rustc::ty::{self, TyCtxt};
 use rustc_hir as hir;
 
 pub trait IsPrefixOf<'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool;
+    fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
 }
 
-impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx, 'tcx> {
-    fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool {
+impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> {
+    fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool {
         self.local == other.local
             && self.projection.len() <= other.projection.len()
             && self.projection == &other.projection[..self.projection.len()]
@@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
     body: ReadOnlyBodyAndCache<'cx, 'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: PrefixSet,
-    next: Option<PlaceRef<'tcx, 'tcx>>,
+    next: Option<PlaceRef<'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// terminating the iteration early based on `kind`.
     pub(super) fn prefixes(
         &self,
-        place_ref: PlaceRef<'tcx, 'tcx>,
+        place_ref: PlaceRef<'tcx>,
         kind: PrefixSet,
     ) -> Prefixes<'cx, 'tcx> {
         Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
@@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 }
 
 impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
-    type Item = PlaceRef<'tcx, 'tcx>;
+    type Item = PlaceRef<'tcx>;
     fn next(&mut self) -> Option<Self::Item> {
         let mut cursor = self.next?;
 
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index fb7ae102a0f18..0272e0c3a872a 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -483,7 +483,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         self.builder.data.loc_map[self.loc].push(move_out);
     }
 
-    fn gather_init(&mut self, place: PlaceRef<'tcx, 'tcx>, kind: InitKind) {
+    fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
         debug!("gather_init({:?}, {:?})", self.loc, place);
 
         let mut place = place;
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 6f6ba7dc27128..593952bfa7c80 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -312,7 +312,7 @@ impl MovePathLookup {
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
     // parent.
-    pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
+    pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
         let mut result = self.locals[place.local];
 
         for elem in place.projection.iter() {
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index a5b467c1e101f..a12d6e02a80b1 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -14,7 +14,7 @@ pub struct AddRetag;
 /// after the assignment, we can be sure to obtain the same place value.
 /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
 /// copies.  Data races are UB.)
-fn is_stable(place: PlaceRef<'_, '_>) -> bool {
+fn is_stable(place: PlaceRef<'_>) -> bool {
     place.projection.iter().all(|elem| {
         match elem {
             // Which place this evaluates to can change with any memory write,
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 275b6e4d508f0..baff8383c20a4 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -35,7 +35,7 @@ pub trait Qualif {
     fn in_projection_structurally(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
     ) -> bool {
         if let [proj_base @ .., elem] = place.projection {
             let base_qualif = Self::in_place(
@@ -67,7 +67,7 @@ pub trait Qualif {
     fn in_projection(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
     ) -> bool {
         Self::in_projection_structurally(cx, per_local, place)
     }
@@ -75,7 +75,7 @@ pub trait Qualif {
     fn in_place(
         cx: &ConstCx<'_, 'tcx>,
         per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx, 'tcx>,
+        place: PlaceRef<'tcx>,
     ) -> bool {
         match place {
             PlaceRef { local, projection: [] } => per_local(local),
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 286740f99dde6..33f4e126f1efd 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -474,7 +474,7 @@ impl<'tcx> Validator<'_, 'tcx> {
         }
     }
 
-    fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
+    fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
         match place {
             PlaceRef { local, projection: [] } => self.validate_local(local),
             PlaceRef { local: _, projection: [proj_base @ .., elem] } => {

From c1df945a610bb6eddfe0dc5ff033722fa611ef09 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Tue, 3 Mar 2020 01:06:07 +0300
Subject: [PATCH 23/34] rustc_metadata: Give decoder access to whole crate
 store

---
 src/librustc_metadata/creader.rs              | 24 ++++++++++--
 src/librustc_metadata/rmeta/decoder.rs        | 39 +++++++++++--------
 .../rmeta/decoder/cstore_impl.rs              |  2 +-
 3 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 5254471051ffd..18b4c9ad5044c 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -76,6 +76,21 @@ impl<'a> LoadError<'a> {
     }
 }
 
+/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
+#[derive(Clone, Copy)]
+crate struct CrateMetadataRef<'a> {
+    pub cdata: &'a CrateMetadata,
+    pub cstore: &'a CStore,
+}
+
+impl std::ops::Deref for CrateMetadataRef<'_> {
+    type Target = CrateMetadata;
+
+    fn deref(&self) -> &Self::Target {
+        self.cdata
+    }
+}
+
 fn dump_crates(cstore: &CStore) {
     info!("resolved crates:");
     cstore.iter_crate_data(|cnum, data| {
@@ -100,10 +115,11 @@ impl CStore {
         CrateNum::new(self.metas.len() - 1)
     }
 
-    crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
-        self.metas[cnum]
+    crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
+        let cdata = self.metas[cnum]
             .as_ref()
-            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
+            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
+        CrateMetadataRef { cdata, cstore: self }
     }
 
     fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
@@ -217,7 +233,7 @@ impl<'a> CrateLoader<'a> {
             // We're also sure to compare *paths*, not actual byte slices. The
             // `source` stores paths which are normalized which may be different
             // from the strings on the command line.
-            let source = self.cstore.get_crate_data(cnum).source();
+            let source = self.cstore.get_crate_data(cnum).cdata.source();
             if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
                 if let Some(mut files) = entry.files() {
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index a72ee0cbe4729..5dec7bfe60cbd 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1,5 +1,6 @@
 // Decoding metadata from a single crate's metadata
 
+use crate::creader::CrateMetadataRef;
 use crate::rmeta::table::{FixedSizeEncoding, Table};
 use crate::rmeta::*;
 
@@ -125,7 +126,7 @@ struct ImportedSourceFile {
 
 pub(super) struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
-    cdata: Option<&'a CrateMetadata>,
+    cdata: Option<CrateMetadataRef<'a>>,
     sess: Option<&'tcx Session>,
     tcx: Option<TyCtxt<'tcx>>,
 
@@ -141,7 +142,7 @@ pub(super) struct DecodeContext<'a, 'tcx> {
 /// Abstract over the various ways one can create metadata decoders.
 pub(super) trait Metadata<'a, 'tcx>: Copy {
     fn raw_bytes(self) -> &'a [u8];
-    fn cdata(self) -> Option<&'a CrateMetadata> {
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         None
     }
     fn sess(self) -> Option<&'tcx Session> {
@@ -162,7 +163,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
             lazy_state: LazyState::NoNode,
             alloc_decoding_session: self
                 .cdata()
-                .map(|cdata| cdata.alloc_decoding_state.new_decoding_session()),
+                .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
         }
     }
 }
@@ -185,33 +186,33 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
     fn raw_bytes(self) -> &'a [u8] {
         self.blob.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'tcx Session) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
     fn raw_bytes(self) -> &'a [u8] {
         self.0.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self.0)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self.0)
     }
     fn sess(self) -> Option<&'tcx Session> {
         Some(&self.1)
     }
 }
 
-impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
     fn raw_bytes(self) -> &'a [u8] {
         self.0.raw_bytes()
     }
-    fn cdata(self) -> Option<&'a CrateMetadata> {
-        Some(self.0)
+    fn cdata(self) -> Option<CrateMetadataRef<'a>> {
+        Some(*self.0)
     }
     fn tcx(self) -> Option<TyCtxt<'tcx>> {
         Some(self.1)
@@ -242,7 +243,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
         self.tcx.expect("missing TyCtxt in DecodeContext")
     }
 
-    fn cdata(&self) -> &'a CrateMetadata {
+    fn cdata(&self) -> CrateMetadataRef<'a> {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
@@ -558,7 +559,7 @@ impl CrateRoot<'_> {
     }
 }
 
-impl<'a, 'tcx> CrateMetadata {
+impl CrateMetadata {
     crate fn new(
         sess: &Session,
         blob: MetadataBlob,
@@ -601,7 +602,9 @@ impl<'a, 'tcx> CrateMetadata {
             extern_crate: Lock::new(None),
         }
     }
+}
 
+impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn is_proc_macro(&self, id: DefIndex) -> bool {
         self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
     }
@@ -1440,10 +1443,10 @@ impl<'a, 'tcx> CrateMetadata {
     /// Proc macro crates don't currently export spans, so this function does not have
     /// to work for them.
     fn imported_source_files(
-        &'a self,
+        &self,
         local_source_map: &source_map::SourceMap,
-    ) -> &[ImportedSourceFile] {
-        self.source_map_import_info.init_locking(|| {
+    ) -> &'a [ImportedSourceFile] {
+        self.cdata.source_map_import_info.init_locking(|| {
             let external_source_map = self.root.source_map.decode(self);
 
             external_source_map
@@ -1540,7 +1543,9 @@ impl<'a, 'tcx> CrateMetadata {
 
         dep_node_index
     }
+}
 
+impl CrateMetadata {
     crate fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> {
         self.dependencies.borrow()
     }
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index be229350f3bcc..c890640d432a7 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -517,7 +517,7 @@ impl CrateStore for CStore {
     }
 
     fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
-        &self.get_crate_data(cnum).def_path_table
+        &self.get_crate_data(cnum).cdata.def_path_table
     }
 
     fn crates_untracked(&self) -> Vec<CrateNum> {

From 41374d748b3c8bc39a78adf703d7d5560a4a8ab7 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Tue, 3 Mar 2020 22:56:27 +0300
Subject: [PATCH 24/34] rustc_metadata: Move some code from `impl
 CrateMetadataRef` to `impl CrateMetadata`

---
 src/librustc_metadata/rmeta/decoder.rs | 176 ++++++++++++-------------
 1 file changed, 87 insertions(+), 89 deletions(-)

diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 5dec7bfe60cbd..e60ae5b6c25ee 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -559,51 +559,6 @@ impl CrateRoot<'_> {
     }
 }
 
-impl CrateMetadata {
-    crate fn new(
-        sess: &Session,
-        blob: MetadataBlob,
-        root: CrateRoot<'static>,
-        raw_proc_macros: Option<&'static [ProcMacro]>,
-        cnum: CrateNum,
-        cnum_map: CrateNumMap,
-        dep_kind: DepKind,
-        source: CrateSource,
-        private_dep: bool,
-        host_hash: Option<Svh>,
-    ) -> CrateMetadata {
-        let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
-            root.def_path_table.decode((&blob, sess))
-        });
-        let trait_impls = root
-            .impls
-            .decode((&blob, sess))
-            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
-            .collect();
-        let alloc_decoding_state =
-            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
-        let dependencies = Lock::new(cnum_map.iter().cloned().collect());
-        CrateMetadata {
-            blob,
-            root,
-            def_path_table,
-            trait_impls,
-            raw_proc_macros,
-            source_map_import_info: Once::new(),
-            alloc_decoding_state,
-            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
-            cnum,
-            cnum_map,
-            dependencies,
-            dep_kind: Lock::new(dep_kind),
-            source,
-            private_dep,
-            host_hash,
-            extern_crate: Lock::new(None),
-        }
-    }
-}
-
 impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn is_proc_macro(&self, id: DefIndex) -> bool {
         self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
@@ -625,10 +580,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         })
     }
 
-    fn local_def_id(&self, index: DefIndex) -> DefId {
-        DefId { krate: self.cnum, index }
-    }
-
     fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
         // DefIndex's in root.proc_macro_data have a one-to-one correspondence
         // with items in 'raw_proc_macros'.
@@ -1194,18 +1145,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .collect()
     }
 
-    // Translate a DefId from the current compilation environment to a DefId
-    // for an external crate.
-    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
-        for (local, &global) in self.cnum_map.iter_enumerated() {
-            if global == did.krate {
-                return Some(DefId { krate: local, index: did.index });
-            }
-        }
-
-        None
-    }
-
     fn get_inherent_implementations_for_type(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -1412,11 +1351,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
-    #[inline]
-    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.def_path_table.def_path_hash(index)
-    }
-
     /// Imports the source_map from an external crate into the source_map of the crate
     /// currently being compiled (the "local crate").
     ///
@@ -1519,33 +1453,52 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 .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 {
-        let mut dep_node_index = self.dep_node_index.load();
-
-        if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
-            // We have not cached the DepNodeIndex for this upstream crate yet,
-            // so use the dep-graph to find it out and cache it.
-            // Note that multiple threads can enter this block concurrently.
-            // That is fine because the DepNodeIndex remains constant
-            // throughout the whole compilation session, and multiple stores
-            // would always write the same value.
-
-            let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
-            let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
-
-            dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
-            assert!(dep_node_index != DepNodeIndex::INVALID);
-            self.dep_node_index.store(dep_node_index);
+impl CrateMetadata {
+    crate fn new(
+        sess: &Session,
+        blob: MetadataBlob,
+        root: CrateRoot<'static>,
+        raw_proc_macros: Option<&'static [ProcMacro]>,
+        cnum: CrateNum,
+        cnum_map: CrateNumMap,
+        dep_kind: DepKind,
+        source: CrateSource,
+        private_dep: bool,
+        host_hash: Option<Svh>,
+    ) -> CrateMetadata {
+        let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
+            root.def_path_table.decode((&blob, sess))
+        });
+        let trait_impls = root
+            .impls
+            .decode((&blob, sess))
+            .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
+            .collect();
+        let alloc_decoding_state =
+            AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
+        let dependencies = Lock::new(cnum_map.iter().cloned().collect());
+        CrateMetadata {
+            blob,
+            root,
+            def_path_table,
+            trait_impls,
+            raw_proc_macros,
+            source_map_import_info: Once::new(),
+            alloc_decoding_state,
+            dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
+            cnum,
+            cnum_map,
+            dependencies,
+            dep_kind: Lock::new(dep_kind),
+            source,
+            private_dep,
+            host_hash,
+            extern_crate: Lock::new(None),
         }
-
-        dep_node_index
     }
-}
 
-impl CrateMetadata {
     crate fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> {
         self.dependencies.borrow()
     }
@@ -1618,6 +1571,51 @@ impl CrateMetadata {
     crate fn hash(&self) -> Svh {
         self.root.hash
     }
+
+    fn local_def_id(&self, index: DefIndex) -> DefId {
+        DefId { krate: self.cnum, index }
+    }
+
+    // Translate a DefId from the current compilation environment to a DefId
+    // for an external crate.
+    fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
+        for (local, &global) in self.cnum_map.iter_enumerated() {
+            if global == did.krate {
+                return Some(DefId { krate: local, index: did.index });
+            }
+        }
+
+        None
+    }
+
+    #[inline]
+    fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+        self.def_path_table.def_path_hash(index)
+    }
+
+    /// 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 {
+        let mut dep_node_index = self.dep_node_index.load();
+
+        if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
+            // We have not cached the DepNodeIndex for this upstream crate yet,
+            // so use the dep-graph to find it out and cache it.
+            // Note that multiple threads can enter this block concurrently.
+            // That is fine because the DepNodeIndex remains constant
+            // throughout the whole compilation session, and multiple stores
+            // would always write the same value.
+
+            let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
+            let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
+
+            dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
+            assert!(dep_node_index != DepNodeIndex::INVALID);
+            self.dep_node_index.store(dep_node_index);
+        }
+
+        dep_node_index
+    }
 }
 
 // Cannot be implemented on 'ProcMacro', as libproc_macro

From f77afc8f9c63d789519c0b1a733462ca654d894a Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Sat, 7 Mar 2020 12:04:40 +0100
Subject: [PATCH 25/34] Allow ZSTs in `AllocRef`

---
 src/liballoc/alloc.rs         | 34 +++++++++++++++++----
 src/liballoc/raw_vec.rs       | 38 +++++++++++-------------
 src/liballoc/raw_vec/tests.rs |  2 +-
 src/libcore/alloc.rs          | 56 ++++++++---------------------------
 src/libstd/alloc.rs           | 47 ++++++++++++++++++++++-------
 5 files changed, 96 insertions(+), 81 deletions(-)

diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index 73e8121868aba..9f82b2c6fa66d 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -165,13 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
 #[unstable(feature = "allocator_api", issue = "32838")]
 unsafe impl AllocRef for Global {
     #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) }
+        }
     }
 
     #[inline]
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        dealloc(ptr.as_ptr(), layout)
+        if layout.size() != 0 {
+            dealloc(ptr.as_ptr(), layout)
+        }
     }
 
     #[inline]
@@ -181,12 +187,28 @@ unsafe impl AllocRef for Global {
         layout: Layout,
         new_size: usize,
     ) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr).map(|p| (p, new_size))
+        match (layout.size(), new_size) {
+            (0, 0) => Ok((layout.dangling(), 0)),
+            (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
+            (_, 0) => {
+                self.dealloc(ptr, layout);
+                Ok((layout.dangling(), 0))
+            }
+            (_, _) => NonNull::new(realloc(ptr.as_ptr(), layout, new_size))
+                .ok_or(AllocErr)
+                .map(|p| (p, new_size)),
+        }
     }
 
     #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
+            }
+        }
     }
 }
 
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 345834d7daacc..b31fec7f037c9 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -73,30 +73,28 @@ impl<T, A: AllocRef> RawVec<T, A> {
     }
 
     fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self {
-        unsafe {
-            let elem_size = mem::size_of::<T>();
+        let elem_size = mem::size_of::<T>();
 
-            let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
-            alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
+        let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
+        alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
 
-            // Handles ZSTs and `capacity == 0` alike.
-            let ptr = if alloc_size == 0 {
-                NonNull::<T>::dangling()
-            } else {
-                let align = mem::align_of::<T>();
-                let layout = Layout::from_size_align(alloc_size, align).unwrap();
-                let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
-                match result {
-                    Ok((ptr, size)) => {
-                        capacity = size / elem_size;
-                        ptr.cast()
-                    }
-                    Err(_) => handle_alloc_error(layout),
+        // Handles ZSTs and `capacity == 0` alike.
+        let ptr = if alloc_size == 0 {
+            NonNull::<T>::dangling()
+        } else {
+            let align = mem::align_of::<T>();
+            let layout = Layout::from_size_align(alloc_size, align).unwrap();
+            let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
+            match result {
+                Ok((ptr, size)) => {
+                    capacity = size / elem_size;
+                    ptr.cast()
                 }
-            };
+                Err(_) => handle_alloc_error(layout),
+            }
+        };
 
-            RawVec { ptr: ptr.into(), cap: capacity, a }
-        }
+        RawVec { ptr: ptr.into(), cap: capacity, a }
     }
 }
 
diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs
index 860058debe1fd..21a8a76d0a75b 100644
--- a/src/liballoc/raw_vec/tests.rs
+++ b/src/liballoc/raw_vec/tests.rs
@@ -20,7 +20,7 @@ fn allocator_param() {
         fuel: usize,
     }
     unsafe impl AllocRef for BoundedAlloc {
-        unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
             let size = layout.size();
             if size > self.fuel {
                 return Err(AllocErr);
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 0a7a8ab266aee..d2a513451ccb6 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -606,20 +606,11 @@ pub unsafe trait GlobalAlloc {
 ///   method (`dealloc`) or by being passed to a reallocation method
 ///  (see above) that returns `Ok`.
 ///
-/// A note regarding zero-sized types and zero-sized layouts: many
-/// methods in the `AllocRef` trait state that allocation requests
-/// must be non-zero size, or else undefined behavior can result.
-///
-/// * If an `AllocRef` implementation chooses to return `Ok` in this
-///   case (i.e., the pointer denotes a zero-sized inaccessible block)
-///   then that returned pointer must be considered "currently
-///   allocated". On such an allocator, *all* methods that take
-///   currently-allocated pointers as inputs must accept these
-///   zero-sized pointers, *without* causing undefined behavior.
-///
-/// * In other words, if a zero-sized pointer can flow out of an
-///   allocator, then that allocator must likewise accept that pointer
-///   flowing back into its deallocation and reallocation methods.
+/// Unlike [`GlobalAlloc`], zero-sized allocations are allowed in
+/// `AllocRef`. If an underlying allocator does not support this (like
+/// jemalloc) or return a null pointer (such as `libc::malloc`), this case
+/// must be caught. In this case [`Layout::dangling()`] can be used to
+/// create a dangling, but aligned `NonNull<u8>`.
 ///
 /// Some of the methods require that a layout *fit* a memory block.
 /// What it means for a layout to "fit" a memory block means (or
@@ -649,6 +640,9 @@ pub unsafe trait GlobalAlloc {
 ///  * if an allocator does not support overallocating, it is fine to
 ///    simply return `layout.size()` as the allocated size.
 ///
+/// [`GlobalAlloc`]: self::GlobalAlloc
+/// [`Layout::dangling()`]: self::Layout::dangling
+///
 /// # Safety
 ///
 /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
@@ -669,14 +663,6 @@ pub unsafe trait GlobalAlloc {
 /// the future.
 #[unstable(feature = "allocator_api", issue = "32838")]
 pub unsafe trait AllocRef {
-    // (Note: some existing allocators have unspecified but well-defined
-    // behavior in response to a zero size allocation request ;
-    // e.g., in C, `malloc` of 0 will either return a null pointer or a
-    // unique pointer, but will not have arbitrary undefined
-    // behavior.
-    // However in jemalloc for example,
-    // `mallocx(0)` is documented as undefined behavior.)
-
     /// On success, returns a pointer meeting the size and alignment
     /// guarantees of `layout` and the actual size of the allocated block,
     /// which must be greater than or equal to `layout.size()`.
@@ -690,15 +676,6 @@ pub unsafe trait AllocRef {
     /// behavior, e.g., to ensure initialization to particular sets of
     /// bit patterns.)
     ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure that `layout` has non-zero size.
-    ///
-    /// (Extension subtraits might provide more specific bounds on
-    /// behavior, e.g., guarantee a sentinel address or a null pointer
-    /// in response to a zero-size allocation request.)
-    ///
     /// # Errors
     ///
     /// Returning `Err` indicates that either memory is exhausted or
@@ -716,7 +693,7 @@ pub unsafe trait AllocRef {
     /// rather than directly invoking `panic!` or similar.
     ///
     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
 
     /// Deallocate the memory referenced by `ptr`.
     ///
@@ -738,10 +715,6 @@ pub unsafe trait AllocRef {
     /// Behaves like `alloc`, but also ensures that the contents
     /// are set to zero before being returned.
     ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `alloc` is.
-    ///
     /// # Errors
     ///
     /// Returning `Err` indicates that either memory is exhausted or
@@ -753,17 +726,17 @@ pub unsafe trait AllocRef {
     /// rather than directly invoking `panic!` or similar.
     ///
     /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
         let size = layout.size();
         let result = self.alloc(layout);
         if let Ok((p, _)) = result {
-            ptr::write_bytes(p.as_ptr(), 0, size);
+            unsafe { ptr::write_bytes(p.as_ptr(), 0, size) }
         }
         result
     }
 
     // == METHODS FOR MEMORY REUSE ==
-    // realloc. alloc_excess, realloc_excess
+    // realloc, realloc_zeroed, grow_in_place, grow_in_place_zeroed, shrink_in_place
 
     /// Returns a pointer suitable for holding data described by
     /// a new layout with `layout`’s alignment and a size given
@@ -793,8 +766,6 @@ pub unsafe trait AllocRef {
     /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
     ///   argument need not fit it.)
     ///
-    /// * `new_size` must be greater than zero.
-    ///
     /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
     ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
     ///
@@ -1009,8 +980,7 @@ pub unsafe trait AllocRef {
     /// * `layout` must *fit* the `ptr` (see above); note the
     ///   `new_size` argument need not fit it,
     ///
-    /// * `new_size` must not be greater than `layout.size()`
-    ///   (and must be greater than zero),
+    /// * `new_size` must not be greater than `layout.size()`,
     ///
     /// # Errors
     ///
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index 2da18e06d99bf..25f3ddcbebab6 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -133,24 +133,41 @@ pub use alloc_crate::alloc::*;
 #[derive(Debug, Default, Copy, Clone)]
 pub struct System;
 
-// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
+// The AllocRef impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
+// which is in `std::sys::*::alloc`.
 #[unstable(feature = "allocator_api", issue = "32838")]
 unsafe impl AllocRef for System {
     #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
+    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(GlobalAlloc::alloc(self, layout))
+                    .ok_or(AllocErr)
+                    .map(|p| (p, layout.size()))
+            }
+        }
     }
 
     #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout))
-            .ok_or(AllocErr)
-            .map(|p| (p, layout.size()))
+    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
+        if layout.size() == 0 {
+            Ok((layout.dangling(), 0))
+        } else {
+            unsafe {
+                NonNull::new(GlobalAlloc::alloc_zeroed(self, layout))
+                    .ok_or(AllocErr)
+                    .map(|p| (p, layout.size()))
+            }
+        }
     }
 
     #[inline]
     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+        if layout.size() != 0 {
+            GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+        }
     }
 
     #[inline]
@@ -160,9 +177,17 @@ unsafe impl AllocRef for System {
         layout: Layout,
         new_size: usize,
     ) -> Result<(NonNull<u8>, usize), AllocErr> {
-        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size))
-            .ok_or(AllocErr)
-            .map(|p| (p, new_size))
+        match (layout.size(), new_size) {
+            (0, 0) => Ok((layout.dangling(), 0)),
+            (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
+            (_, 0) => {
+                self.dealloc(ptr, layout);
+                Ok((layout.dangling(), 0))
+            }
+            (_, _) => NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size))
+                .ok_or(AllocErr)
+                .map(|p| (p, new_size)),
+        }
     }
 }
 

From d32924f89d1324386588bd23b0437cdeca1e0fc8 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <huyuumi.dev@gmail.com>
Date: Mon, 9 Mar 2020 05:00:03 +0900
Subject: [PATCH 26/34] Check if output is immediate value

---
 src/librustc_codegen_llvm/asm.rs   | 10 ++++++++--
 src/test/ui/asm/issue-62046.rs     | 11 +++++++++++
 src/test/ui/asm/issue-62046.stderr | 11 +++++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 src/test/ui/asm/issue-62046.rs
 create mode 100644 src/test/ui/asm/issue-62046.stderr

diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index c8f0fe8c72395..7975a70ab269c 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -29,11 +29,17 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         let mut indirect_outputs = vec![];
         for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() {
             if out.is_rw {
-                inputs.push(self.load_operand(place).immediate());
+                let operand = self.load_operand(place);
+                if let OperandValue::Immediate(_) = operand.val {
+                    inputs.push(operand.immediate());
+                }
                 ext_constraints.push(i.to_string());
             }
             if out.is_indirect {
-                indirect_outputs.push(self.load_operand(place).immediate());
+                let operand = self.load_operand(place);
+                if let OperandValue::Immediate(_) = operand.val {
+                    indirect_outputs.push(operand.immediate());
+                }
             } else {
                 output_types.push(place.layout.llvm_type(self.cx()));
             }
diff --git a/src/test/ui/asm/issue-62046.rs b/src/test/ui/asm/issue-62046.rs
new file mode 100644
index 0000000000000..105dadd5fd373
--- /dev/null
+++ b/src/test/ui/asm/issue-62046.rs
@@ -0,0 +1,11 @@
+// build-fail
+// ignore-emscripten no asm! support
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("nop" : "+r"("r15"));
+        //~^ malformed inline assembly
+    }
+}
diff --git a/src/test/ui/asm/issue-62046.stderr b/src/test/ui/asm/issue-62046.stderr
new file mode 100644
index 0000000000000..a38a300548d48
--- /dev/null
+++ b/src/test/ui/asm/issue-62046.stderr
@@ -0,0 +1,11 @@
+error[E0668]: malformed inline assembly
+  --> $DIR/issue-62046.rs:8:9
+   |
+LL |         asm!("nop" : "+r"("r15"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0668`.

From c06fa0be82842b1b5c610e7d4243002305fa845f Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 9 Mar 2020 09:31:15 +0100
Subject: [PATCH 27/34] clean up E0393 explanation

---
 src/librustc_error_codes/error_codes/E0393.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/librustc_error_codes/error_codes/E0393.md b/src/librustc_error_codes/error_codes/E0393.md
index 7cce99401cf0c..3e853cf1b8a36 100644
--- a/src/librustc_error_codes/error_codes/E0393.md
+++ b/src/librustc_error_codes/error_codes/E0393.md
@@ -1,5 +1,6 @@
 A type parameter which references `Self` in its default value was not specified.
-Example of erroneous code:
+
+Erroneous code example:
 
 ```compile_fail,E0393
 trait A<T=Self> {}

From b974d6fc306d5847ad4b8bb48a99e6ca234cb6d1 Mon Sep 17 00:00:00 2001
From: Matthew Kuo <matthew.kuo@dialexa.com>
Date: Sat, 7 Mar 2020 22:01:11 -0600
Subject: [PATCH 28/34] test(patterns): add borrowck tests for combination of
 pattern features

Adds borrowck tests for the following features:
- bindings_after_at
- or_patterns
- slice_patterns
- box_patterns
---
 ...or-patterns-slice-patterns-box-patterns.rs | 224 ++++++++++++++++++
 ...atterns-slice-patterns-box-patterns.stderr | 208 ++++++++++++++++
 2 files changed, 432 insertions(+)
 create mode 100644 src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
 create mode 100644 src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr

diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
new file mode 100644
index 0000000000000..b67d494866b85
--- /dev/null
+++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs
@@ -0,0 +1,224 @@
+// Tests using a combination of pattern features has the expected borrow checking behavior
+#![feature(bindings_after_at)]
+#![feature(or_patterns)]
+#![feature(box_patterns)]
+
+#![feature(move_ref_pattern)]
+
+enum Test {
+    Foo,
+    Bar,
+    _Baz,
+}
+
+// bindings_after_at + slice_patterns
+
+fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
+    match x {
+        a @ [.., _] => (),
+        _ => (),
+    };
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_slice_patterns_borrows_binding_mut(mut x: [String; 4]) {
+    let r = match x {
+        ref mut foo @ [.., _] => Some(foo),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_slice_mut1(mut x: [String; 4]) {
+    let r = match x {
+        ref foo @ [.., ref mut bar] => (),
+        //~^ ERROR cannot borrow
+        _ => (),
+    };
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_slice_mut2(mut x: [String; 4]) {
+    let r = match x {
+        [ref foo @ .., ref bar] => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_borrows_both(mut x: [String; 4]) {
+    let r = match x {
+        ref foo @ [.., ref bar] => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + or_patterns
+
+fn bindings_after_at_or_patterns_move(x: Option<Test>) {
+    match x {
+        foo @ Some(Test::Foo | Test::Bar) => (),
+        _ => (),
+    }
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_or_patterns_borrows(mut x: Option<Test>) {
+    let r = match x {
+        ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_or_patterns_borrows_mut(mut x: Option<Test>) {
+    let r = match x {
+        ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + box_patterns
+
+fn bindings_after_at_box_patterns_borrows_both(mut x: Option<Box<String>>) {
+    let r = match x {
+        ref foo @ Some(box ref s) => Some(foo),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_box_patterns_borrows_mut(mut x: Option<Box<String>>) {
+    match x {
+        ref foo @ Some(box ref mut s) => (),
+        //~^ ERROR cannot borrow
+        _ => (),
+    };
+}
+
+// bindings_after_at + slice_patterns + or_patterns
+
+fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
+    match x {
+        a @ [.., Some(Test::Foo | Test::Bar)] => (),
+        _ => (),
+    };
+
+    &x;
+    //~^ ERROR borrow of moved value
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_borrows_binding(mut x: [Option<Test>; 4]) {
+    let r = match x {
+        ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_borrows_slice(mut x: [Option<Test>; 4]) {
+    let r = match x {
+        ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + slice_patterns + box_patterns
+
+fn bindings_after_at_slice_patterns_box_patterns_borrows(mut x: [Option<Box<String>>; 4]) {
+    let r = match x {
+        [_, ref a @ Some(box ref b), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+// bindings_after_at + slice_patterns + or_patterns + box_patterns
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_mut(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_binding(
+    mut x: [Option<Box<Test>>; 4]
+) {
+    let r = match x {
+        ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+        _ => None,
+    };
+
+    &mut x;
+    //~^ ERROR cannot borrow
+
+    drop(r);
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
new file mode 100644
index 0000000000000..35ed2763c2b08
--- /dev/null
+++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -0,0 +1,208 @@
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
+   |
+LL |         ref foo @ [.., ref mut bar] => (),
+   |         -------^^^^^^^^-----------^
+   |         |              |
+   |         |              mutable borrow, by `bar`, occurs here
+   |         immutable borrow, by `foo`, occurs here
+
+error: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
+   |
+LL |         ref foo @ Some(box ref mut s) => (),
+   |         -------^^^^^^^^^^^^---------^
+   |         |                  |
+   |         |                  mutable borrow, by `s`, occurs here
+   |         immutable borrow, by `foo`, occurs here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
+   |
+LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
+   |                                                  - move occurs because `x` has type `[std::string::String; 4]`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         a @ [.., _] => (),
+   |         ----------- value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
+   |
+LL |         ref mut foo @ [.., _] => Some(foo),
+   |         --------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
+   |
+LL |         [ref foo @ .., ref bar] => Some(foo),
+   |          ------------ immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
+   |
+LL |         ref foo @ [.., ref bar] => Some(foo),
+   |         ----------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
+   |
+LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
+   |                                       - move occurs because `x` has type `std::option::Option<Test>`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         foo @ Some(Test::Foo | Test::Bar) => (),
+   |         ---------------------------------
+   |         |
+   |         value moved here
+   |         value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
+   |
+LL |         ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+   |         ------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
+   |
+LL |         ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
+   |         ----------------------------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
+   |
+LL |         ref foo @ Some(box ref s) => Some(foo),
+   |         ------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
+   |
+LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
+   |                                                       - move occurs because `x` has type `[std::option::Option<Test>; 4]`, which does not implement the `Copy` trait
+LL |     match x {
+LL |         a @ [.., Some(Test::Foo | Test::Bar)] => (),
+   |         -------------------------------------
+   |         |
+   |         value moved here
+   |         value moved here
+...
+LL |     &x;
+   |     ^^ value borrowed here after move
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
+   |
+LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
+   |         ------------------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
+   |
+LL |         ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
+   |                  ---------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
+   |
+LL |         [_, ref a @ Some(box ref b), ..] => Some(a),
+   |             ----------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
+   |
+LL |         [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |             ------------------------------------------- immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
+   |
+LL |         [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |             ----------------------------------------------- mutable borrow occurs here
+...
+LL |     &x;
+   |     ^^ immutable borrow occurs here
+...
+LL |     drop(r);
+   |          - mutable borrow later used here
+
+error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
+  --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
+   |
+LL |         ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
+   |         ------------------------------------------------------------ immutable borrow occurs here
+...
+LL |     &mut x;
+   |     ^^^^^^ mutable borrow occurs here
+...
+LL |     drop(r);
+   |          - immutable borrow later used here
+
+error: aborting due to 17 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.

From 67012158a379dbf58318346e87a631e7eb310bd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Wed, 26 Feb 2020 00:26:38 +0100
Subject: [PATCH 29/34] Move `analysis` to the query macro

---
 src/librustc/dep_graph/dep_node.rs |  2 --
 src/librustc/query/mod.rs          |  5 +++++
 src/librustc/ty/query/config.rs    |  9 +--------
 src/librustc/ty/query/mod.rs       |  7 +------
 src/librustc/ty/query/plumbing.rs  | 14 --------------
 5 files changed, 7 insertions(+), 30 deletions(-)

diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index eb7e2871bfcd8..05088dc419339 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -360,8 +360,6 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     [anon] TraitSelect,
 
     [] CompileCodegenUnit(Symbol),
-
-    [eval_always] Analysis(CrateNum),
 ]);
 
 pub trait RecoverKey<'tcx>: Sized {
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index b7f4f432838be..daf89cab8af6d 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -60,6 +60,11 @@ rustc_queries! {
             cache_on_disk_if { key.is_local() }
         }
 
+        query analysis(key: CrateNum) -> Result<(), ErrorReported> {
+            eval_always
+            desc { "running analysis passes on this crate" }
+        }
+
         /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
         /// associated generics.
         query generics_of(key: DefId) -> &'tcx ty::Generics {
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index e0e1ca374d9ae..178c2362def6e 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -2,11 +2,10 @@ use crate::dep_graph::SerializedDepNodeIndex;
 use crate::dep_graph::{DepKind, DepNode};
 use crate::ty::query::caches::QueryCache;
 use crate::ty::query::plumbing::CycleError;
-use crate::ty::query::queries;
 use crate::ty::query::{Query, QueryState};
 use crate::ty::TyCtxt;
 use rustc_data_structures::profiling::ProfileCategory;
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::DefId;
 
 use crate::ich::StableHashingContext;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -87,9 +86,3 @@ where
         bug!("QueryDescription::load_from_disk() called for an unsupported query.")
     }
 }
-
-impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
-    fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
-        "running analysis passes on this crate".into()
-    }
-}
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 8614fd5cdca9a..f49c64a7b87a7 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -104,9 +104,4 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder
 // Queries marked with `fatal_cycle` do not need the latter implementation,
 // as they will raise an fatal error on query cycles instead.
 
-rustc_query_append! { [define_queries!][ <'tcx>
-    Other {
-        /// Runs analysis passes on the crate.
-        [eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
-    },
-]}
+rustc_query_append! { [define_queries!][<'tcx>] }
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index c94909549df22..1769a925ec301 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1246,20 +1246,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
         DepKind::CompileCodegenUnit => {
             bug!("force_from_dep_node: encountered {:?}", dep_node)
         }
-
-        DepKind::Analysis => {
-            let def_id = if let Some(def_id) = dep_node.extract_def_id(tcx) {
-                def_id
-            } else {
-                // Return from the whole function.
-                return false
-            };
-            tcx.force_query::<crate::ty::query::queries::analysis<'_>>(
-                def_id.krate,
-                DUMMY_SP,
-                *dep_node
-            );
-        }
     );
 
     true

From cbce21767b757b209c4d4df6792995fecf02c7fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Wed, 26 Feb 2020 02:20:33 +0100
Subject: [PATCH 30/34] Remove the need for `no_force`

---
 src/librustc/dep_graph/dep_node.rs |  42 ++++++------
 src/librustc/dep_graph/mod.rs      |   3 +-
 src/librustc/query/mod.rs          |   2 +-
 src/librustc/ty/query/mod.rs       | 105 ++++++++++++++++++++++++++++-
 src/librustc/ty/query/plumbing.rs  |  92 +------------------------
 src/librustc_macros/src/query.rs   |  57 ++++++----------
 6 files changed, 148 insertions(+), 153 deletions(-)

diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 05088dc419339..bcb270ff0a64e 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -362,29 +362,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     [] CompileCodegenUnit(Symbol),
 ]);
 
-pub trait RecoverKey<'tcx>: Sized {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
-}
-
-impl RecoverKey<'tcx> for CrateNum {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx).map(|id| id.krate)
-    }
-}
-
-impl RecoverKey<'tcx> for DefId {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx)
-    }
-}
-
-impl RecoverKey<'tcx> for DefIndex {
-    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx).map(|id| id.index)
-    }
-}
-
-trait DepNodeParams<'tcx>: fmt::Debug {
+pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
     const CAN_RECONSTRUCT_QUERY_KEY: bool;
 
     /// This method turns the parameters of a DepNodeConstructor into an opaque
@@ -398,6 +376,8 @@ trait DepNodeParams<'tcx>: fmt::Debug {
     fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
         format!("{:?}", self)
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
 }
 
 impl<'tcx, T> DepNodeParams<'tcx> for T
@@ -418,6 +398,10 @@ where
     default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
         format!("{:?}", *self)
     }
+
+    default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
+        None
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for DefId {
@@ -430,6 +414,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefId {
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.def_path_str(*self)
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx)
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for DefIndex {
@@ -442,6 +430,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefIndex {
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.def_path_str(DefId::local(*self))
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.index)
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for CrateNum {
@@ -455,6 +447,10 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum {
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.crate_name(*self).to_string()
     }
+
+    fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.krate)
+    }
 }
 
 impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index eb377d20f5963..1fbd90743f402 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -6,7 +6,8 @@ mod query;
 mod safe;
 mod serialized;
 
-pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId};
+pub(crate) use self::dep_node::DepNodeParams;
+pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId};
 pub use self::graph::WorkProductFileKind;
 pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
 pub use self::prev::PreviousDepGraph;
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index daf89cab8af6d..c8155005480ff 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
+use crate::dep_graph::SerializedDepNodeIndex;
 use crate::mir;
 use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index f49c64a7b87a7..8adb828fbebc4 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{self, DepConstructor, DepNode};
+use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
 use crate::hir::exports::Export;
 use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintLevelMap;
@@ -60,8 +60,8 @@ use std::sync::Arc;
 
 #[macro_use]
 mod plumbing;
+pub use self::plumbing::CycleError;
 use self::plumbing::*;
-pub use self::plumbing::{force_from_dep_node, CycleError};
 
 mod stats;
 pub use self::stats::print_stats;
@@ -105,3 +105,104 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder
 // as they will raise an fatal error on query cycles instead.
 
 rustc_query_append! { [define_queries!][<'tcx>] }
+
+/// The red/green evaluation system will try to mark a specific DepNode in the
+/// dependency graph as green by recursively trying to mark the dependencies of
+/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+/// where we don't know if it is red or green and we therefore actually have
+/// to recompute its value in order to find out. Since the only piece of
+/// information that we have at that point is the `DepNode` we are trying to
+/// re-evaluate, we need some way to re-run a query from just that. This is what
+/// `force_from_dep_node()` implements.
+///
+/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+/// is usually constructed by computing a stable hash of the query-key that the
+/// `DepNode` corresponds to. Consequently, it is not in general possible to go
+/// back from hash to query-key (since hash functions are not reversible). For
+/// this reason `force_from_dep_node()` is expected to fail from time to time
+/// because we just cannot find out, from the `DepNode` alone, what the
+/// corresponding query-key is and therefore cannot re-run the query.
+///
+/// The system deals with this case letting `try_mark_green` fail which forces
+/// the root query to be re-evaluated.
+///
+/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+/// Fortunately, we can use some contextual information that will allow us to
+/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+/// valid `DefPathHash`. Since we also always build a huge table that maps every
+/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+/// everything we need to re-run the query.
+///
+/// Take the `mir_validated` query as an example. Like many other queries, it
+/// just has a single parameter: the `DefId` of the item it will compute the
+/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+/// is actually a `DefPathHash`, and can therefore just look up the corresponding
+/// `DefId` in `tcx.def_path_hash_to_def_id`.
+///
+/// When you implement a new query, it will likely have a corresponding new
+/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
+/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
+/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
+/// add it to the "We don't have enough information to reconstruct..." group in
+/// the match below.
+pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
+    use crate::dep_graph::DepKind;
+
+    // We must avoid ever having to call `force_from_dep_node()` for a
+    // `DepNode::codegen_unit`:
+    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+    // would always end up having to evaluate the first caller of the
+    // `codegen_unit` query that *is* reconstructible. This might very well be
+    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+    // to re-trigger calling the `codegen_unit` query with the right key. At
+    // that point we would already have re-done all the work we are trying to
+    // avoid doing in the first place.
+    // The solution is simple: Just explicitly call the `codegen_unit` query for
+    // each CGU, right after partitioning. This way `try_mark_green` will always
+    // hit the cache instead of having to go through `force_from_dep_node`.
+    // This assertion makes sure, we actually keep applying the solution above.
+    debug_assert!(
+        dep_node.kind != DepKind::codegen_unit,
+        "calling force_from_dep_node() on DepKind::codegen_unit"
+    );
+
+    if !dep_node.kind.can_reconstruct_query_key() {
+        return false;
+    }
+
+    rustc_dep_node_force!([dep_node, tcx]
+        // These are inputs that are expected to be pre-allocated and that
+        // should therefore always be red or green already.
+        DepKind::AllLocalTraitImpls |
+        DepKind::CrateMetadata |
+        DepKind::HirBody |
+        DepKind::Hir |
+
+        // These are anonymous nodes.
+        DepKind::TraitSelect |
+
+        // We don't have enough information to reconstruct the query key of
+        // these.
+        DepKind::CompileCodegenUnit => {
+            bug!("force_from_dep_node: encountered {:?}", dep_node)
+        }
+    );
+
+    false
+}
+
+impl DepNode {
+    /// Check whether the query invocation corresponding to the given
+    /// DepNode is eligible for on-disk-caching. If so, this is method
+    /// will execute the query corresponding to the given DepNode.
+    /// Also, as a sanity check, it expects that the corresponding query
+    /// invocation has been marked as green already.
+    pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
+        use crate::dep_graph::DepKind;
+
+        rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
+    }
+}
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 1769a925ec301..acf67f52dceaa 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -2,7 +2,7 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
 use crate::ty::query::caches::QueryCache;
 use crate::ty::query::config::{QueryAccessors, QueryDescription};
 use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId};
@@ -720,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[allow(dead_code)]
-    fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
+    pub(super) fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
         self,
         key: Q::Key,
         span: Span,
@@ -1162,91 +1162,3 @@ macro_rules! define_provider_struct {
         }
     };
 }
-
-/// The red/green evaluation system will try to mark a specific DepNode in the
-/// dependency graph as green by recursively trying to mark the dependencies of
-/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
-/// where we don't know if it is red or green and we therefore actually have
-/// to recompute its value in order to find out. Since the only piece of
-/// information that we have at that point is the `DepNode` we are trying to
-/// re-evaluate, we need some way to re-run a query from just that. This is what
-/// `force_from_dep_node()` implements.
-///
-/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
-/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
-/// is usually constructed by computing a stable hash of the query-key that the
-/// `DepNode` corresponds to. Consequently, it is not in general possible to go
-/// back from hash to query-key (since hash functions are not reversible). For
-/// this reason `force_from_dep_node()` is expected to fail from time to time
-/// because we just cannot find out, from the `DepNode` alone, what the
-/// corresponding query-key is and therefore cannot re-run the query.
-///
-/// The system deals with this case letting `try_mark_green` fail which forces
-/// the root query to be re-evaluated.
-///
-/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
-/// Fortunately, we can use some contextual information that will allow us to
-/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
-/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
-/// valid `DefPathHash`. Since we also always build a huge table that maps every
-/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
-/// everything we need to re-run the query.
-///
-/// Take the `mir_validated` query as an example. Like many other queries, it
-/// just has a single parameter: the `DefId` of the item it will compute the
-/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
-/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
-/// is actually a `DefPathHash`, and can therefore just look up the corresponding
-/// `DefId` in `tcx.def_path_hash_to_def_id`.
-///
-/// When you implement a new query, it will likely have a corresponding new
-/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
-/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
-/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
-/// add it to the "We don't have enough information to reconstruct..." group in
-/// the match below.
-pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
-    use crate::dep_graph::RecoverKey;
-
-    // We must avoid ever having to call `force_from_dep_node()` for a
-    // `DepNode::codegen_unit`:
-    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
-    // would always end up having to evaluate the first caller of the
-    // `codegen_unit` query that *is* reconstructible. This might very well be
-    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
-    // to re-trigger calling the `codegen_unit` query with the right key. At
-    // that point we would already have re-done all the work we are trying to
-    // avoid doing in the first place.
-    // The solution is simple: Just explicitly call the `codegen_unit` query for
-    // each CGU, right after partitioning. This way `try_mark_green` will always
-    // hit the cache instead of having to go through `force_from_dep_node`.
-    // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(
-        dep_node.kind != DepKind::codegen_unit,
-        "calling force_from_dep_node() on DepKind::codegen_unit"
-    );
-
-    if !dep_node.kind.can_reconstruct_query_key() {
-        return false;
-    }
-
-    rustc_dep_node_force!([dep_node, tcx]
-        // These are inputs that are expected to be pre-allocated and that
-        // should therefore always be red or green already.
-        DepKind::AllLocalTraitImpls |
-        DepKind::CrateMetadata |
-        DepKind::HirBody |
-        DepKind::Hir |
-
-        // These are anonymous nodes.
-        DepKind::TraitSelect |
-
-        // We don't have enough information to reconstruct the query key of
-        // these.
-        DepKind::CompileCodegenUnit => {
-            bug!("force_from_dep_node: encountered {:?}", dep_node)
-        }
-    );
-
-    true
-}
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index 97b800decc59b..c23095968fb3e 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -425,7 +425,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
     let mut dep_node_def_stream = quote! {};
     let mut dep_node_force_stream = quote! {};
     let mut try_load_from_on_disk_cache_stream = quote! {};
-    let mut no_force_queries = Vec::new();
     let mut cached_queries = quote! {};
 
     for group in groups.0 {
@@ -444,19 +443,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 cached_queries.extend(quote! {
                     #name,
                 });
-            }
 
-            if modifiers.cache.is_some() && !modifiers.no_force {
                 try_load_from_on_disk_cache_stream.extend(quote! {
                     DepKind::#name => {
-                        debug_assert!(tcx.dep_graph
-                                         .node_color(self)
-                                         .map(|c| c.is_green())
-                                         .unwrap_or(false));
-
-                        let key = RecoverKey::recover(tcx, self).unwrap();
-                        if queries::#name::cache_on_disk(tcx, key, None) {
-                            let _ = tcx.#name(key);
+                        if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
+                            debug_assert!($tcx.dep_graph
+                                            .node_color($dep_node)
+                                            .map(|c| c.is_green())
+                                            .unwrap_or(false));
+
+                            let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap();
+                            if queries::#name::cache_on_disk($tcx, key, None) {
+                                let _ = $tcx.#name(key);
+                            }
                         }
                     }
                 });
@@ -501,24 +500,21 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 [#attribute_stream] #name(#arg),
             });
 
-            if modifiers.no_force {
-                no_force_queries.push(name.clone());
-            } else {
-                // Add a match arm to force the query given the dep node
-                dep_node_force_stream.extend(quote! {
-                    DepKind::#name => {
-                        if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
+            // Add a match arm to force the query given the dep node
+            dep_node_force_stream.extend(quote! {
+                DepKind::#name => {
+                    if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
+                        if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) {
                             $tcx.force_query::<crate::ty::query::queries::#name<'_>>(
                                 key,
                                 DUMMY_SP,
                                 *$dep_node
                             );
-                        } else {
-                            return false;
+                            return true;
                         }
                     }
-                });
-            }
+                }
+            });
 
             add_query_description_impl(&query, modifiers, &mut query_description_stream);
         }
@@ -528,12 +524,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
         });
     }
 
-    // Add an arm for the no force queries to panic when trying to force them
-    for query in no_force_queries {
-        dep_node_force_stream.extend(quote! {
-            DepKind::#query |
-        });
-    }
     dep_node_force_stream.extend(quote! {
         DepKind::Null => {
             bug!("Cannot force dep node: {:?}", $dep_node)
@@ -577,14 +567,9 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
 
         #query_description_stream
 
-        impl DepNode {
-            /// Check whether the query invocation corresponding to the given
-            /// DepNode is eligible for on-disk-caching. If so, this is method
-            /// will execute the query corresponding to the given DepNode.
-            /// Also, as a sanity check, it expects that the corresponding query
-            /// invocation has been marked as green already.
-            pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
-                match self.kind {
+        macro_rules! rustc_dep_node_try_load_from_on_disk_cache {
+            ($dep_node:expr, $tcx:expr) => {
+                match $dep_node.kind {
                     #try_load_from_on_disk_cache_stream
                     _ => (),
                 }

From f4450772ede7bc064d1727430acdb1b2dc851742 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Wed, 26 Feb 2020 02:39:18 +0100
Subject: [PATCH 31/34] Remove the `no_force` query attribute

---
 src/librustc/query/mod.rs        | 38 --------------------------------
 src/librustc_macros/src/query.rs | 16 --------------
 2 files changed, 54 deletions(-)

diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index c8155005480ff..11e9acf3a3912 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -200,7 +200,6 @@ rustc_queries! {
             // queries). Making it anonymous avoids hashing the result, which
             // may save a bit of time.
             anon
-            no_force
             desc { "erasing regions from `{:?}`", ty }
         }
 
@@ -209,7 +208,6 @@ rustc_queries! {
         }
 
         query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
-            no_force
             desc { "generating chalk-style clauses for environment" }
         }
 
@@ -252,7 +250,6 @@ rustc_queries! {
         /// To avoid cycles within the predicates of a single item we compute
         /// per-type-parameter predicates for resolving `T::AssocTy`.
         query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> {
-            no_force
             desc { |tcx| "computing the bounds for type parameter `{}`", {
                 let id = tcx.hir().as_local_hir_id(key.1).unwrap();
                 tcx.hir().ty_param_name(id)
@@ -508,7 +505,6 @@ rustc_queries! {
         /// form to be used outside of const eval.
         query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalRawResult<'tcx> {
-            no_force
             desc { |tcx|
                 "const-evaluating `{}`",
                 tcx.def_path_str(key.value.instance.def.def_id())
@@ -525,7 +521,6 @@ rustc_queries! {
         /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
         query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
             -> ConstEvalResult<'tcx> {
-            no_force
             desc { |tcx|
                 "const-evaluating + checking `{}`",
                 tcx.def_path_str(key.value.instance.def.def_id())
@@ -540,7 +535,6 @@ rustc_queries! {
         query const_field(
             key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
         ) -> ConstValue<'tcx> {
-            no_force
             desc { "extract field of const" }
         }
 
@@ -549,19 +543,16 @@ rustc_queries! {
         query destructure_const(
             key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
         ) -> mir::DestructuredConst<'tcx> {
-            no_force
             desc { "destructure constant" }
         }
 
         query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
-            no_force
             desc { "get a &core::panic::Location referring to a span" }
         }
 
         query lit_to_const(
             key: LitToConstInput<'tcx>
         ) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
-            no_force
             desc { "converting literal to const" }
         }
     }
@@ -592,7 +583,6 @@ rustc_queries! {
         query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
 
         query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> {
-            no_force
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
 
@@ -600,7 +590,6 @@ rustc_queries! {
         /// given instance from the local crate. In particular, it will also
         /// look up the correct symbol name of instances from upstream crates.
         query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
-            no_force
             desc { "computing the symbol for `{}`", key }
             cache_on_disk_if { true }
         }
@@ -647,7 +636,6 @@ rustc_queries! {
     Other {
         query vtable_methods(key: ty::PolyTraitRef<'tcx>)
                             -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-            no_force
             desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
         }
     }
@@ -656,7 +644,6 @@ rustc_queries! {
         query codegen_fulfill_obligation(
             key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
         ) -> Option<Vtable<'tcx, ()>> {
-            no_force
             cache_on_disk_if { true }
             desc { |tcx|
                 "checking if `{}` fulfills its obligations",
@@ -688,22 +675,18 @@ rustc_queries! {
         /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
         /// `ty.is_copy()`, etc, since that will prune the environment where possible.
         query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is `Copy`", env.value }
         }
         /// Query backing `TyS::is_sized`.
         query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is `Sized`", env.value }
         }
         /// Query backing `TyS::is_freeze`.
         query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` is freeze", env.value }
         }
         /// Query backing `TyS::needs_drop`.
         query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-            no_force
             desc { "computing whether `{}` needs drop", env.value }
         }
 
@@ -717,7 +700,6 @@ rustc_queries! {
         query layout_raw(
             env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
         ) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> {
-            no_force
             desc { "computing layout of `{}`", env.value }
         }
     }
@@ -773,7 +755,6 @@ rustc_queries! {
 
     TypeChecking {
         query specializes(_: (DefId, DefId)) -> bool {
-            no_force
             desc { "computing whether impls specialize one another" }
         }
         query in_scope_traits_map(_: DefIndex)
@@ -858,7 +839,6 @@ rustc_queries! {
         ///       (like `Clone::clone` for example).
         query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
             desc { "available upstream drop-glue for `{:?}`", substs }
-            no_force
         }
     }
 
@@ -903,7 +883,6 @@ rustc_queries! {
     TypeChecking {
         query implementations_of_trait(_: (CrateNum, DefId))
             -> &'tcx [DefId] {
-            no_force
             desc { "looking up implementations of a trait in a crate" }
         }
         query all_trait_implementations(_: CrateNum)
@@ -1070,7 +1049,6 @@ rustc_queries! {
         }
         query is_codegened_item(_: DefId) -> bool {}
         query codegen_unit(_: Symbol) -> Arc<CodegenUnit<'tcx>> {
-            no_force
             desc { "codegen_unit" }
         }
         query backend_optimization_level(_: CrateNum) -> OptLevel {
@@ -1093,7 +1071,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1101,7 +1078,6 @@ rustc_queries! {
         query normalize_ty_after_erasing_regions(
             goal: ParamEnvAnd<'tcx, Ty<'tcx>>
         ) -> Ty<'tcx> {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1111,7 +1087,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
             NoSolution,
         > {
-            no_force
             desc { "computing implied outlives bounds for `{:?}`", goal }
         }
 
@@ -1122,7 +1097,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "computing dropck types for `{:?}`", goal }
         }
 
@@ -1131,7 +1105,6 @@ rustc_queries! {
         query evaluate_obligation(
             goal: CanonicalPredicateGoal<'tcx>
         ) -> Result<traits::EvaluationResult, traits::OverflowError> {
-            no_force
             desc { "evaluating trait selection obligation `{}`", goal.value.value }
         }
 
@@ -1142,7 +1115,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
         }
 
@@ -1153,7 +1125,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_eq` `{:?}`", goal }
         }
 
@@ -1164,7 +1135,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_subtype` `{:?}`", goal }
         }
 
@@ -1175,7 +1145,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution,
         > {
-            no_force
             desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
         }
 
@@ -1186,7 +1155,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1197,7 +1165,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1208,7 +1175,6 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
@@ -1219,12 +1185,10 @@ rustc_queries! {
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
             NoSolution,
         > {
-            no_force
             desc { "normalizing `{:?}`", goal }
         }
 
         query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
-            no_force
             desc { |tcx|
                 "testing substituted normalized predicates:`{}`",
                 tcx.def_path_str(key.0)
@@ -1234,7 +1198,6 @@ rustc_queries! {
         query method_autoderef_steps(
             goal: CanonicalTyGoal<'tcx>
         ) -> MethodAutoderefStepsResult<'tcx> {
-            no_force
             desc { "computing autoderef types for `{:?}`", goal }
         }
     }
@@ -1248,7 +1211,6 @@ rustc_queries! {
         // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
         query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
             -> usize {
-            no_force
             desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
         }
 
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index c23095968fb3e..56b7be2f7e2d5 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -51,9 +51,6 @@ enum QueryModifier {
     /// Don't hash the result, instead just mark a query red if it runs
     NoHash,
 
-    /// Don't force the query
-    NoForce,
-
     /// Generate a dep node based on the dependencies of the query
     Anon,
 
@@ -118,8 +115,6 @@ impl Parse for QueryModifier {
             Ok(QueryModifier::CycleDelayBug)
         } else if modifier == "no_hash" {
             Ok(QueryModifier::NoHash)
-        } else if modifier == "no_force" {
-            Ok(QueryModifier::NoForce)
         } else if modifier == "anon" {
             Ok(QueryModifier::Anon)
         } else if modifier == "eval_always" {
@@ -222,9 +217,6 @@ struct QueryModifiers {
     /// Don't hash the result, instead just mark a query red if it runs
     no_hash: bool,
 
-    /// Don't force the query
-    no_force: bool,
-
     /// Generate a dep node based on the dependencies of the query
     anon: bool,
 
@@ -241,7 +233,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
     let mut fatal_cycle = false;
     let mut cycle_delay_bug = false;
     let mut no_hash = false;
-    let mut no_force = false;
     let mut anon = false;
     let mut eval_always = false;
     for modifier in query.modifiers.0.drain(..) {
@@ -288,12 +279,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 no_hash = true;
             }
-            QueryModifier::NoForce => {
-                if no_force {
-                    panic!("duplicate modifier `no_force` for query `{}`", query.name);
-                }
-                no_force = true;
-            }
             QueryModifier::Anon => {
                 if anon {
                     panic!("duplicate modifier `anon` for query `{}`", query.name);
@@ -316,7 +301,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
         fatal_cycle,
         cycle_delay_bug,
         no_hash,
-        no_force,
         anon,
         eval_always,
     }

From 2f120095b59320d8c0adc3ad8f9294560bdf5c07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Mon, 9 Mar 2020 14:50:09 +0100
Subject: [PATCH 32/34] Add a comment to `recover`.

---
 src/librustc/dep_graph/dep_node.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index bcb270ff0a64e..156f412e0902e 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -377,6 +377,12 @@ pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
         format!("{:?}", self)
     }
 
+    /// This method tries to recover the query key from the given `DepNode`,
+    /// something which is needed when forcing `DepNode`s during red-green
+    /// evaluation. The query system will only call this method if
+    /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
+    /// It is always valid to return `None` here, in which case incremental
+    /// compilation will treat the query as having changed instead of forcing it.
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
 }
 

From 7c60405dd63a2d5720251c97ec209d8844f56395 Mon Sep 17 00:00:00 2001
From: Dylan Nugent <dylnuge@gmail.com>
Date: Mon, 9 Mar 2020 12:31:33 -0400
Subject: [PATCH 33/34] Add note about localization to std::fmt docs

---
 src/liballoc/fmt.rs | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index e6162e0f571e2..13ef2f063f95f 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -247,6 +247,21 @@
 //! Hello, `     123` has 3 right-aligned characters
 //! ```
 //!
+//! ## Localization
+//!
+//! In some programming languages, the behavior of string formatting functions
+//! depends on the operating system's locale setting. The format functions
+//! provided by Rust's standard library do not have any concept of locale, and
+//! will produce the same results on all systems regardless of user
+//! configuration.
+//!
+//! For example, the following code will always print `1.5` even if the system
+//! locale uses a decimal separator other than a dot.
+//!
+//! ```
+//! println!("The value is {}", 1.5);
+//! ```
+//!
 //! # Escaping
 //!
 //! The literal characters `{` and `}` may be included in a string by preceding

From a56196205b1919bee851bdfd7e76e9b3ae5090db Mon Sep 17 00:00:00 2001
From: Christopher Durham <cad97@cad97.com>
Date: Mon, 9 Mar 2020 23:07:04 -0400
Subject: [PATCH 34/34] Vec::new is const tstable in 1.39 not 1.32

---
 src/liballoc/vec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 61416f2b906d3..f661b83042868 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -317,7 +317,7 @@ impl<T> Vec<T> {
     /// let mut vec: Vec<i32> = Vec::new();
     /// ```
     #[inline]
-    #[rustc_const_stable(feature = "const_vec_new", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn new() -> Vec<T> {
         Vec { buf: RawVec::NEW, len: 0 }