From eafeb9a2676e16ed322e9e0695b5ce9407f5de8d Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Mon, 30 Dec 2019 21:38:43 +0300
Subject: [PATCH 01/12] expand/builtin_macros: Minor cleanup

---
 src/librustc_builtin_macros/util.rs   |  2 +-
 src/librustc_expand/base.rs           | 13 +++----------
 src/librustc_feature/builtin_attrs.rs |  8 +-------
 3 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/src/librustc_builtin_macros/util.rs b/src/librustc_builtin_macros/util.rs
index 8ef76a8657e1e..b486eadd1a8be 100644
--- a/src/librustc_builtin_macros/util.rs
+++ b/src/librustc_builtin_macros/util.rs
@@ -6,7 +6,7 @@ use rustc_span::Symbol;
 
 pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
     // All the built-in macro attributes are "words" at the moment.
-    let template = AttributeTemplate::only_word();
+    let template = AttributeTemplate { word: true, ..Default::default() };
     let attr = ecx.attribute(meta_item.clone());
     validate_attr::check_builtin_attribute(ecx.parse_sess, &attr, name, template);
 }
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index f15e626c2783b..55e9c70d63732 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -270,10 +270,9 @@ pub trait MultiItemModifier {
     ) -> Vec<Annotatable>;
 }
 
-impl<F, T> MultiItemModifier for F
+impl<F> MultiItemModifier for F
 where
-    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T,
-    T: Into<Vec<Annotatable>>,
+    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
 {
     fn expand(
         &self,
@@ -282,13 +281,7 @@ where
         meta_item: &ast::MetaItem,
         item: Annotatable,
     ) -> Vec<Annotatable> {
-        (*self)(ecx, span, meta_item, item).into()
-    }
-}
-
-impl Into<Vec<Annotatable>> for Annotatable {
-    fn into(self) -> Vec<Annotatable> {
-        vec![self]
+        self(ecx, span, meta_item, item)
     }
 }
 
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index e9a5364c65838..e0e38c2dba941 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -85,19 +85,13 @@ impl AttributeGate {
 
 /// A template that the attribute input must match.
 /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
 pub struct AttributeTemplate {
     pub word: bool,
     pub list: Option<&'static str>,
     pub name_value_str: Option<&'static str>,
 }
 
-impl AttributeTemplate {
-    pub fn only_word() -> Self {
-        Self { word: true, list: None, name_value_str: None }
-    }
-}
-
 /// A convenience macro for constructing attribute templates.
 /// E.g., `template!(Word, List: "description")` means that the attribute
 /// supports forms `#[attr]` and `#[attr(description)]`.

From 552a8875bd5520c2e8c01ab05a12c304c730c5b9 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Mon, 9 Mar 2020 20:50:12 +0300
Subject: [PATCH 02/12] expand: Implement support for retrying macro expansions

---
 src/librustc_builtin_macros/deriving/mod.rs |   6 +-
 src/librustc_expand/base.rs                 |  19 ++-
 src/librustc_expand/expand.rs               | 145 ++++++++++++++------
 src/librustc_expand/proc_macro.rs           |   8 +-
 4 files changed, 124 insertions(+), 54 deletions(-)

diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs
index 5ba9d3800e118..b5ad67abf6201 100644
--- a/src/librustc_builtin_macros/deriving/mod.rs
+++ b/src/librustc_builtin_macros/deriving/mod.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast::ast::{self, ItemKind, MetaItem};
 use rustc_ast::ptr::P;
-use rustc_expand::base::{Annotatable, ExtCtxt, MultiItemModifier};
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
@@ -48,13 +48,13 @@ impl MultiItemModifier for BuiltinDerive {
         span: Span,
         meta_item: &MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         // FIXME: Built-in derives often forget to give spans contexts,
         // so we are doing it here in a centralized way.
         let span = ecx.with_def_site_ctxt(span);
         let mut items = Vec::new();
         (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
-        items
+        ExpandResult::Ready(items)
     }
 }
 
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 55e9c70d63732..3782746a57de4 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -258,8 +258,17 @@ impl Annotatable {
     }
 }
 
-// `meta_item` is the annotation, and `item` is the item being modified.
-// FIXME Decorators should follow the same pattern too.
+/// Result of an expansion that may need to be retried.
+/// Consider using this for non-`MultiItemModifier` expanders as well.
+pub enum ExpandResult<T, U> {
+    /// Expansion produced a result (possibly dummy).
+    Ready(T),
+    /// Expansion could not produce a result and needs to be retried.
+    /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
+    Retry(U, String),
+}
+
+// `meta_item` is the attribute, and `item` is the item being modified.
 pub trait MultiItemModifier {
     fn expand(
         &self,
@@ -267,7 +276,7 @@ pub trait MultiItemModifier {
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable>;
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
 }
 
 impl<F> MultiItemModifier for F
@@ -280,8 +289,8 @@ where
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
-        self(ecx, span, meta_item, item)
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        ExpandResult::Ready(self(ecx, span, meta_item, item))
     }
 }
 
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index effa89e8bfb21..f2af6755517f1 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
-            let invoc = if let Some(invoc) = invocations.pop() {
+            let (invoc, res) = if let Some(invoc) = invocations.pop() {
                 invoc
             } else {
                 self.resolve_imports();
@@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 continue;
             };
 
-            let eager_expansion_root =
-                if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id };
-            let res = match self.cx.resolver.resolve_macro_invocation(
-                &invoc,
-                eager_expansion_root,
-                force,
-            ) {
-                Ok(res) => res,
-                Err(Indeterminate) => {
-                    undetermined_invocations.push(invoc);
-                    continue;
+            let res = match res {
+                Some(res) => res,
+                None => {
+                    let eager_expansion_root = if self.monotonic {
+                        invoc.expansion_data.id
+                    } else {
+                        orig_expansion_data.id
+                    };
+                    match self.cx.resolver.resolve_macro_invocation(
+                        &invoc,
+                        eager_expansion_root,
+                        force,
+                    ) {
+                        Ok(res) => res,
+                        Err(Indeterminate) => {
+                            // Cannot resolve, will retry this invocation later.
+                            undetermined_invocations.push((invoc, None));
+                            continue;
+                        }
+                    }
                 }
             };
 
-            progress = true;
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
 
             // FIXME(jseyfried): Refactor out the following logic
             let (expanded_fragment, new_invocations) = match res {
-                InvocationRes::Single(ext) => {
-                    let fragment = self.expand_invoc(invoc, &ext.kind);
-                    self.collect_invocations(fragment, &[])
-                }
+                InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
+                    ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
+                    ExpandResult::Retry(invoc, explanation) => {
+                        if force {
+                            // We are stuck, stop retrying and produce a dummy fragment.
+                            let span = invoc.span();
+                            self.cx.span_err(span, &explanation);
+                            let fragment = invoc.fragment_kind.dummy(span);
+                            self.collect_invocations(fragment, &[])
+                        } else {
+                            // Cannot expand, will retry this invocation later.
+                            undetermined_invocations
+                                .push((invoc, Some(InvocationRes::Single(ext))));
+                            continue;
+                        }
+                    }
+                },
                 InvocationRes::DeriveContainer(_exts) => {
                     // FIXME: Consider using the derive resolutions (`_exts`) immediately,
                     // instead of enqueuing the derives to be resolved again later.
@@ -463,14 +484,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     for path in derives {
                         let expn_id = ExpnId::fresh(None);
                         derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
-                        invocations.push(Invocation {
-                            kind: InvocationKind::Derive { path, item: item.clone() },
-                            fragment_kind: invoc.fragment_kind,
-                            expansion_data: ExpansionData {
-                                id: expn_id,
-                                ..invoc.expansion_data.clone()
+                        invocations.push((
+                            Invocation {
+                                kind: InvocationKind::Derive { path, item: item.clone() },
+                                fragment_kind: invoc.fragment_kind,
+                                expansion_data: ExpansionData {
+                                    id: expn_id,
+                                    ..invoc.expansion_data.clone()
+                                },
                             },
-                        });
+                            None,
+                        ));
                     }
                     let fragment =
                         invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
@@ -478,6 +502,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
             };
 
+            progress = true;
             if expanded_fragments.len() < depth {
                 expanded_fragments.push(Vec::new());
             }
@@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         &mut self,
         mut fragment: AstFragment,
         extra_placeholders: &[NodeId],
-    ) -> (AstFragment, Vec<Invocation>) {
+    ) -> (AstFragment, Vec<(Invocation, Option<InvocationRes>)>) {
         // Resolve `$crate`s in the fragment for pretty-printing.
         self.cx.resolver.resolve_dollar_crates();
 
@@ -635,13 +660,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         self.cx.trace_macros_diag();
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
+    fn expand_invoc(
+        &mut self,
+        invoc: Invocation,
+        ext: &SyntaxExtensionKind,
+    ) -> ExpandResult<AstFragment, Invocation> {
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
             self.error_recursion_limit_reached();
         }
 
         let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
-        match invoc.kind {
+        ExpandResult::Ready(match invoc.kind {
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
                     self.gate_proc_macro_expansion_kind(span, fragment_kind);
@@ -663,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 _ => unreachable!(),
             },
-            InvocationKind::Attr { attr, mut item, .. } => match ext {
+            InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
@@ -679,8 +708,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::LegacyAttr(expander) => {
                     match validate_attr::parse_meta(self.cx.parse_sess, &attr) {
                         Ok(meta) => {
-                            let item = expander.expand(self.cx, span, &meta, item);
-                            fragment_kind.expect_from_annotatables(item)
+                            let items = match expander.expand(self.cx, span, &meta, item) {
+                                ExpandResult::Ready(items) => items,
+                                ExpandResult::Retry(item, explanation) => {
+                                    // Reassemble the original invocation for retrying.
+                                    return ExpandResult::Retry(
+                                        Invocation {
+                                            kind: InvocationKind::Attr {
+                                                attr,
+                                                item,
+                                                derives,
+                                                after_derive,
+                                            },
+                                            ..invoc
+                                        },
+                                        explanation,
+                                    );
+                                }
+                            };
+                            fragment_kind.expect_from_annotatables(items)
                         }
                         Err(mut err) => {
                             err.emit();
@@ -702,19 +748,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::Derive(expander)
                 | SyntaxExtensionKind::LegacyDerive(expander) => {
                     if !item.derive_allowed() {
-                        return fragment_kind.dummy(span);
+                        return ExpandResult::Ready(fragment_kind.dummy(span));
                     }
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
                     let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
-                    let items = expander.expand(self.cx, span, &meta, item);
+                    let items = match expander.expand(self.cx, span, &meta, item) {
+                        ExpandResult::Ready(items) => items,
+                        ExpandResult::Retry(item, explanation) => {
+                            // Reassemble the original invocation for retrying.
+                            return ExpandResult::Retry(
+                                Invocation {
+                                    kind: InvocationKind::Derive { path: meta.path, item },
+                                    ..invoc
+                                },
+                                explanation,
+                            );
+                        }
+                    };
                     fragment_kind.expect_from_annotatables(items)
                 }
                 _ => unreachable!(),
             },
             InvocationKind::DeriveContainer { .. } => unreachable!(),
-        }
+        })
     }
 
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
@@ -933,7 +991,7 @@ pub fn ensure_complete_parse<'a>(
 struct InvocationCollector<'a, 'b> {
     cx: &'a mut ExtCtxt<'b>,
     cfg: StripUnconfigured<'a>,
-    invocations: Vec<Invocation>,
+    invocations: Vec<(Invocation, Option<InvocationRes>)>,
     monotonic: bool,
 }
 
@@ -955,15 +1013,18 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         };
         let expn_id = ExpnId::fresh(expn_data);
         let vis = kind.placeholder_visibility();
-        self.invocations.push(Invocation {
-            kind,
-            fragment_kind,
-            expansion_data: ExpansionData {
-                id: expn_id,
-                depth: self.cx.current_expansion.depth + 1,
-                ..self.cx.current_expansion.clone()
+        self.invocations.push((
+            Invocation {
+                kind,
+                fragment_kind,
+                expansion_data: ExpansionData {
+                    id: expn_id,
+                    depth: self.cx.current_expansion.depth + 1,
+                    ..self.cx.current_expansion.clone()
+                },
             },
-        });
+            None,
+        ));
         placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
     }
 
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 84a546345bb28..cb9afa4cd4f02 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -79,7 +79,7 @@ impl MultiItemModifier for ProcMacroDerive {
         span: Span,
         _meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let item = match item {
             Annotatable::Arm(..)
             | Annotatable::Field(..)
@@ -99,7 +99,7 @@ impl MultiItemModifier for ProcMacroDerive {
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         };
         match item.kind {
@@ -110,7 +110,7 @@ impl MultiItemModifier for ProcMacroDerive {
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         }
 
@@ -158,7 +158,7 @@ impl MultiItemModifier for ProcMacroDerive {
             FatalError.raise();
         }
 
-        items
+        ExpandResult::Ready(items)
     }
 }
 

From 2e6528961c44a4f3841fd319af71f1d1a6af029c Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Tue, 10 Mar 2020 00:56:20 +0300
Subject: [PATCH 03/12] builtin_macros: Add attribute macro
 `#[cfg_accessible(path)]`

---
 src/libcore/macros/mod.rs                     | 12 +++++
 src/libcore/prelude/v1.rs                     |  9 ++++
 src/librustc_builtin_macros/cfg_accessible.rs | 54 +++++++++++++++++++
 src/librustc_builtin_macros/lib.rs            |  2 +
 src/librustc_expand/base.rs                   |  1 +
 src/librustc_resolve/macros.rs                | 36 +++++++++++++
 src/librustc_span/symbol.rs                   |  1 +
 src/libstd/lib.rs                             |  1 +
 src/libstd/prelude/v1.rs                      |  9 ++++
 .../cfg_accessible-input-validation.rs        | 24 +++++++++
 .../cfg_accessible-input-validation.stderr    | 44 +++++++++++++++
 .../cfg_accessible-stuck.rs                   |  9 ++++
 .../cfg_accessible-stuck.stderr               | 14 +++++
 .../cfg_accessible-unstable.rs                |  2 +
 .../cfg_accessible-unstable.stderr            | 12 +++++
 .../conditional-compilation/cfg_accessible.rs | 43 +++++++++++++++
 .../cfg_accessible.stderr                     | 38 +++++++++++++
 17 files changed, 311 insertions(+)
 create mode 100644 src/librustc_builtin_macros/cfg_accessible.rs
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible.rs
 create mode 100644 src/test/ui/conditional-compilation/cfg_accessible.stderr

diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index 76e58f0cc62bc..3b615a5246c29 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -1383,6 +1383,18 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
+    /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise.
+    #[cfg(not(bootstrap))]
+    #[unstable(
+        feature = "cfg_accessible",
+        issue = "64797",
+        reason = "`cfg_accessible` is not fully implemented"
+    )]
+    #[rustc_builtin_macro]
+    pub macro cfg_accessible($item:item) {
+        /* compiler built-in */
+    }
+
     /// Unstable implementation detail of the `rustc` compiler, do not use.
     #[rustc_builtin_macro]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index 66b5a90b77b91..c91370b271992 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -67,3 +67,12 @@ pub use crate::{
 pub use crate::macros::builtin::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
+
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(no_inline)]
+pub use crate::macros::builtin::cfg_accessible;
diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs
new file mode 100644
index 0000000000000..3607a4d0d15b6
--- /dev/null
+++ b/src/librustc_builtin_macros/cfg_accessible.rs
@@ -0,0 +1,54 @@
+//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
+
+use rustc_ast::ast;
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
+use rustc_feature::AttributeTemplate;
+use rustc_parse::validate_attr;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+crate struct Expander;
+
+fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
+    match mi.meta_item_list() {
+        None => {}
+        Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
+        Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
+        Some([nmi]) => match nmi.meta_item() {
+            None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
+            Some(mi) => {
+                if !mi.is_word() {
+                    ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
+                }
+                return Some(&mi.path);
+            }
+        },
+    }
+    None
+}
+
+impl MultiItemModifier for Expander {
+    fn expand(
+        &self,
+        ecx: &mut ExtCtxt<'_>,
+        _span: Span,
+        meta_item: &ast::MetaItem,
+        item: Annotatable,
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        let template = AttributeTemplate { list: Some("path"), ..Default::default() };
+        let attr = &ecx.attribute(meta_item.clone());
+        validate_attr::check_builtin_attribute(ecx.parse_sess, attr, sym::cfg_accessible, template);
+
+        let path = match validate_input(ecx, meta_item) {
+            Some(path) => path,
+            None => return ExpandResult::Ready(Vec::new()),
+        };
+
+        let failure_msg = "cannot determine whether the path is accessible or not";
+        match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
+            Ok(true) => ExpandResult::Ready(vec![item]),
+            Ok(false) => ExpandResult::Ready(Vec::new()),
+            Err(_) => ExpandResult::Retry(item, failure_msg.into()),
+        }
+    }
+}
diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs
index 9a8b0a87cb793..26a59c6b1bedb 100644
--- a/src/librustc_builtin_macros/lib.rs
+++ b/src/librustc_builtin_macros/lib.rs
@@ -22,6 +22,7 @@ use rustc_span::symbol::sym;
 mod asm;
 mod assert;
 mod cfg;
+mod cfg_accessible;
 mod compile_error;
 mod concat;
 mod concat_idents;
@@ -85,6 +86,7 @@ pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) {
 
     register_attr! {
         bench: test::expand_bench,
+        cfg_accessible: cfg_accessible::Expander,
         global_allocator: global_allocator::expand,
         test: test::expand_test,
         test_case: test::expand_test_case,
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 3782746a57de4..4839651ac844b 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -897,6 +897,7 @@ pub trait Resolver {
 
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
     fn add_derive_copy(&mut self, expn_id: ExpnId);
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
 }
 
 #[derive(Clone)]
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index e11aec906693e..4e41ea82c47c9 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -339,6 +339,42 @@ impl<'a> base::Resolver for Resolver<'a> {
     fn add_derive_copy(&mut self, expn_id: ExpnId) {
         self.containers_deriving_copy.insert(expn_id);
     }
+
+    // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
+    // Returns true if the path can certainly be resolved in one of three namespaces,
+    // returns false if the path certainly cannot be resolved in any of the three namespaces.
+    // Returns `Indeterminate` if we cannot give a certain answer yet.
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
+        let span = path.span;
+        let path = &Segment::from_path(path);
+        let parent_scope = self.invocation_parent_scopes[&expn_id];
+
+        let mut indeterminate = false;
+        for ns in [TypeNS, ValueNS, MacroNS].iter().copied() {
+            match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) {
+                PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
+                PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
+                    return Ok(true);
+                }
+                PathResult::Indeterminate => indeterminate = true,
+                // FIXME: `resolve_path` is not ready to report partially resolved paths
+                // correctly, so we just report an error if the path was reported as unresolved.
+                // This needs to be fixed for `cfg_accessible` to be useful.
+                PathResult::NonModule(..) | PathResult::Failed { .. } => {}
+                PathResult::Module(_) => panic!("unexpected path resolution"),
+            }
+        }
+
+        if indeterminate {
+            return Err(Indeterminate);
+        }
+
+        self.session
+            .struct_span_err(span, "not sure whether the path is accessible or not")
+            .span_note(span, "`cfg_accessible` is not fully implemented")
+            .emit();
+        Ok(false)
+    }
 }
 
 impl<'a> Resolver<'a> {
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index c39f9f360c027..55284e73efcfa 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -181,6 +181,7 @@ symbols! {
         caller_location,
         cdylib,
         cfg,
+        cfg_accessible,
         cfg_attr,
         cfg_attr_multi,
         cfg_doctest,
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 784868b52e517..9950a8132555f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -240,6 +240,7 @@
 #![feature(atomic_mut_ptr)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
+#![cfg_attr(not(bootstrap), feature(cfg_accessible))]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 7c0efe828c27a..6712f5ba5808c 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -53,6 +53,15 @@ pub use core::prelude::v1::{
     PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
 };
 
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(hidden)]
+pub use core::prelude::v1::cfg_accessible;
+
 // The file so far is equivalent to src/libcore/prelude/v1.rs,
 // and below to src/liballoc/prelude.rs.
 // Those files are duplicated rather than using glob imports
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
new file mode 100644
index 0000000000000..c51c908a4262e
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
@@ -0,0 +1,24 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input
+struct S1;
+
+#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input
+struct S2;
+
+#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified
+struct S3;
+
+#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified
+struct S4;
+
+#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal
+struct S5;
+
+#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S6;
+
+#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S7;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
new file mode 100644
index 0000000000000..86706c766356e
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
@@ -0,0 +1,44 @@
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:3:1
+   |
+LL | #[cfg_accessible]
+   | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:6:1
+   |
+LL | #[cfg_accessible = "value"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: `cfg_accessible` path is not specified
+  --> $DIR/cfg_accessible-input-validation.rs:9:1
+   |
+LL | #[cfg_accessible()]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: multiple `cfg_accessible` paths are specified
+  --> $DIR/cfg_accessible-input-validation.rs:12:23
+   |
+LL | #[cfg_accessible(std, core)]
+   |                       ^^^^
+
+error: `cfg_accessible` path cannot be a literal
+  --> $DIR/cfg_accessible-input-validation.rs:15:18
+   |
+LL | #[cfg_accessible("std")]
+   |                  ^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:18:18
+   |
+LL | #[cfg_accessible(std = "value")]
+   |                  ^^^^^^^^^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:21:18
+   |
+LL | #[cfg_accessible(std(value))]
+   |                  ^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
new file mode 100644
index 0000000000000..8bc93fa324378
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
@@ -0,0 +1,9 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not
+struct S;
+
+#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not
+struct Z;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
new file mode 100644
index 0000000000000..9641441a819b0
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
@@ -0,0 +1,14 @@
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:6:1
+   |
+LL | #[cfg_accessible(S)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:3:1
+   |
+LL | #[cfg_accessible(Z)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
new file mode 100644
index 0000000000000..e9247e67a2a26
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
@@ -0,0 +1,2 @@
+#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible'
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
new file mode 100644
index 0000000000000..2f55b9559c78f
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible-unstable.rs:1:3
+   |
+LL | #[cfg_accessible(std)]
+   |   ^^^^^^^^^^^^^^
+   |
+   = note: see issue #64797 <https://github.com/rust-lang/rust/issues/64797> for more information
+   = help: add `#![feature(cfg_accessible)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg_accessible.rs b/src/test/ui/conditional-compilation/cfg_accessible.rs
new file mode 100644
index 0000000000000..07b0be5b1ae26
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible.rs
@@ -0,0 +1,43 @@
+#![feature(cfg_accessible)]
+
+mod m {
+    pub struct ExistingPublic;
+    struct ExistingPrivate;
+}
+
+#[cfg_accessible(m::ExistingPublic)]
+struct ExistingPublic;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::ExistingPrivate)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::NonExistent)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry.
+struct AccessibleExpanded;
+
+macro_rules! generate_accessible_expanded {
+    () => {
+        mod n {
+            pub struct AccessibleExpanded;
+        }
+    };
+}
+
+generate_accessible_expanded!();
+
+struct S {
+    field: u8,
+}
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(S::field)] //~ ERROR not sure whether the path is accessible or not
+struct Field;
+
+fn main() {
+    ExistingPublic;
+    AccessibleExpanded;
+}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible.stderr b/src/test/ui/conditional-compilation/cfg_accessible.stderr
new file mode 100644
index 0000000000000..167765cd66ee6
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible.stderr
@@ -0,0 +1,38 @@
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+
+error: aborting due to 3 previous errors
+

From 71ebc6182012d80e076e4aaa03e0dbe44132fcbf Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 7 Mar 2020 18:39:16 +0300
Subject: [PATCH 04/12] resolve: Simplify `fn report_privacy_error`

by factoring out `fn ctor_fields_span` into a separate function
---
 src/librustc_resolve/diagnostics.rs | 67 +++++++++++++----------------
 1 file changed, 31 insertions(+), 36 deletions(-)

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 47a05ec90d42f..edbb2db3868d4 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -916,51 +916,46 @@ impl<'a> Resolver<'a> {
         err.emit();
     }
 
-    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
-        let PrivacyError { ident, binding, .. } = *privacy_error;
-        let session = &self.session;
-        let mk_struct_span_error = |is_constructor| {
-            let mut descr = binding.res().descr().to_string();
-            if is_constructor {
-                descr += " constructor";
-            }
-            if binding.is_import() {
-                descr += " import";
-            }
-
-            let mut err =
-                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
-
-            err.span_label(ident.span, &format!("this {} is private", descr));
-            err.span_note(
-                session.source_map().def_span(binding.span),
-                &format!("the {} `{}` is defined here", descr, ident),
-            );
-
-            err
-        };
-
-        let mut err = if let NameBindingKind::Res(
+    /// If the binding refers to a tuple struct constructor with fields,
+    /// returns the span of its fields.
+    fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
+        if let NameBindingKind::Res(
             Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
             _,
         ) = binding.kind
         {
             let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
             if let Some(fields) = self.field_names.get(&def_id) {
-                let mut err = mk_struct_span_error(true);
                 let first_field = fields.first().expect("empty field list in the map");
-                err.span_label(
-                    fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
-                    "a constructor is private if any of the fields is private",
-                );
-                err
-            } else {
-                mk_struct_span_error(false)
+                return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)));
             }
-        } else {
-            mk_struct_span_error(false)
-        };
+        }
+        None
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+
+        let ctor_fields_span = self.ctor_fields_span(binding);
+        let mut descr = binding.res().descr().to_string();
+        if ctor_fields_span.is_some() {
+            descr += " constructor";
+        }
+        if binding.is_import() {
+            descr += " import";
+        }
 
+        let mut err =
+            struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
+        err.span_label(ident.span, &format!("this {} is private", descr));
+        if let Some(span) = ctor_fields_span {
+            err.span_label(span, "a constructor is private if any of the fields is private");
+        }
+
+        err.span_note(
+            self.session.source_map().def_span(binding.span),
+            &format!("the {} `{}` is defined here", descr, ident),
+        );
         err.emit();
     }
 }

From 580c6a29d47a9cd786c89df98d97e6de13f49291 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 7 Mar 2020 21:18:29 +0300
Subject: [PATCH 05/12] resolve: Print import chains on privacy errors

---
 src/librustc_resolve/diagnostics.rs           | 61 +++++++++++++++----
 src/test/ui/imports/issue-55884-2.stderr      | 17 +++++-
 src/test/ui/imports/reexports.stderr          | 14 ++++-
 src/test/ui/privacy/privacy2.stderr           |  7 ++-
 .../shadowed/shadowed-use-visibility.stderr   | 14 ++++-
 5 files changed, 95 insertions(+), 18 deletions(-)

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index edbb2db3868d4..063c62ad9aac7 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,4 +1,5 @@
 use std::cmp::Reverse;
+use std::ptr;
 
 use log::debug;
 use rustc::bug;
@@ -936,15 +937,17 @@ impl<'a> Resolver<'a> {
     crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
         let PrivacyError { ident, binding, .. } = *privacy_error;
 
+        let res = binding.res();
         let ctor_fields_span = self.ctor_fields_span(binding);
-        let mut descr = binding.res().descr().to_string();
-        if ctor_fields_span.is_some() {
-            descr += " constructor";
-        }
-        if binding.is_import() {
-            descr += " import";
-        }
-
+        let plain_descr = res.descr().to_string();
+        let nonimport_descr =
+            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
+        let import_descr = nonimport_descr.clone() + " import";
+        let get_descr =
+            |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
+
+        // Print the primary message.
+        let descr = get_descr(binding);
         let mut err =
             struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("this {} is private", descr));
@@ -952,10 +955,44 @@ impl<'a> Resolver<'a> {
             err.span_label(span, "a constructor is private if any of the fields is private");
         }
 
-        err.span_note(
-            self.session.source_map().def_span(binding.span),
-            &format!("the {} `{}` is defined here", descr, ident),
-        );
+        // Print the whole import chain to make it easier to see what happens.
+        let first_binding = binding;
+        let mut next_binding = Some(binding);
+        let mut next_ident = ident;
+        while let Some(binding) = next_binding {
+            let name = next_ident;
+            next_binding = match binding.kind {
+                _ if res == Res::Err => None,
+                NameBindingKind::Import { binding, import, .. } => match import.kind {
+                    _ if binding.span.is_dummy() => None,
+                    ImportKind::Single { source, .. } => {
+                        next_ident = source;
+                        Some(binding)
+                    }
+                    ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding),
+                    ImportKind::ExternCrate { .. } => None,
+                },
+                _ => None,
+            };
+
+            let first = ptr::eq(binding, first_binding);
+            let descr = get_descr(binding);
+            let msg = format!(
+                "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
+                and_refers_to = if first { "" } else { "...and refers to " },
+                item = descr,
+                name = name,
+                which = if first { "" } else { " which" },
+                dots = if next_binding.is_some() { "..." } else { "" },
+            );
+            let def_span = self.session.source_map().def_span(binding.span);
+            let mut note_span = MultiSpan::from_span(def_span);
+            if !first && next_binding.is_none() && binding.vis == ty::Visibility::Public {
+                note_span.push_span_label(def_span, "consider importing it directly".into());
+            }
+            err.span_note(note_span, &msg);
+        }
+
         err.emit();
     }
 }
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
index f16d2adb3656e..3eee7118e5a22 100644
--- a/src/test/ui/imports/issue-55884-2.stderr
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -4,11 +4,26 @@ error[E0603]: struct import `ParseOptions` is private
 LL | pub use parser::ParseOptions;
    |                 ^^^^^^^^^^^^ this struct import is private
    |
-note: the struct import `ParseOptions` is defined here
+note: the struct import `ParseOptions` is defined here...
   --> $DIR/issue-55884-2.rs:9:9
    |
 LL |     use ParseOptions;
    |         ^^^^^^^^^^^^
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:12:9
+   |
+LL | pub use parser::ParseOptions;
+   |         ^^^^^^^^^^^^^^^^^^^^
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:6:13
+   |
+LL |     pub use options::*;
+   |             ^^^^^^^^^^
+note: ...and refers to the struct `ParseOptions` which is defined here
+  --> $DIR/issue-55884-2.rs:2:5
+   |
+LL |     pub struct ParseOptions {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr
index 7b0d63574ec8e..d63fbc7ec6781 100644
--- a/src/test/ui/imports/reexports.stderr
+++ b/src/test/ui/imports/reexports.stderr
@@ -16,11 +16,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::a::foo::S;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:21:17
    |
 LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
    |                 ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
@@ -28,11 +33,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::b::foo::S as T;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:26:17
    |
 LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
    |                 ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
index 719dc27ccf4d6..b10c3a5265971 100644
--- a/src/test/ui/privacy/privacy2.stderr
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -10,11 +10,16 @@ error[E0603]: function import `foo` is private
 LL |     use bar::glob::foo;
    |                    ^^^ this function import is private
    |
-note: the function import `foo` is defined here
+note: the function import `foo` is defined here...
   --> $DIR/privacy2.rs:10:13
    |
 LL |         use foo;
    |             ^^^
+note: ...and refers to the function `foo` which is defined here
+  --> $DIR/privacy2.rs:14:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^ consider importing it directly
 
 error: requires `sized` lang_item
 
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr
index cd8ec13794c6f..2244f3a46b266 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.stderr
+++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr
@@ -4,11 +4,16 @@ error[E0603]: module import `bar` is private
 LL |     use foo::bar::f as g;
    |              ^^^ this module import is private
    |
-note: the module import `bar` is defined here
+note: the module import `bar` is defined here...
   --> $DIR/shadowed-use-visibility.rs:4:9
    |
 LL |     use foo as bar;
    |         ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
@@ -16,11 +21,16 @@ error[E0603]: module import `f` is private
 LL | use bar::f::f;
    |          ^ this module import is private
    |
-note: the module import `f` is defined here
+note: the module import `f` is defined here...
   --> $DIR/shadowed-use-visibility.rs:11:9
    |
 LL |     use foo as f;
    |         ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 

From f4083c6455ad47e0369013dba7eb716eb00223eb Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Wed, 11 Mar 2020 21:17:23 +0300
Subject: [PATCH 06/12] Add the "consider importing it directly" label to
 public imports as well

---
 src/librustc_resolve/diagnostics.rs      | 2 +-
 src/test/ui/imports/issue-55884-2.stderr | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 063c62ad9aac7..b00c7473bace3 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -987,7 +987,7 @@ impl<'a> Resolver<'a> {
             );
             let def_span = self.session.source_map().def_span(binding.span);
             let mut note_span = MultiSpan::from_span(def_span);
-            if !first && next_binding.is_none() && binding.vis == ty::Visibility::Public {
+            if !first && binding.vis == ty::Visibility::Public {
                 note_span.push_span_label(def_span, "consider importing it directly".into());
             }
             err.span_note(note_span, &msg);
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
index 3eee7118e5a22..490c08446b5a8 100644
--- a/src/test/ui/imports/issue-55884-2.stderr
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -13,12 +13,12 @@ note: ...and refers to the struct import `ParseOptions` which is defined here...
   --> $DIR/issue-55884-2.rs:12:9
    |
 LL | pub use parser::ParseOptions;
-   |         ^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^ consider importing it directly
 note: ...and refers to the struct import `ParseOptions` which is defined here...
   --> $DIR/issue-55884-2.rs:6:13
    |
 LL |     pub use options::*;
-   |             ^^^^^^^^^^
+   |             ^^^^^^^^^^ consider importing it directly
 note: ...and refers to the struct `ParseOptions` which is defined here
   --> $DIR/issue-55884-2.rs:2:5
    |

From e80cb2032cac39db2226ba940fad05b5adb17e62 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 14 Mar 2020 15:28:17 +0300
Subject: [PATCH 07/12] resolve: Fix regression in resolution of raw keywords
 in paths

---
 src/librustc_resolve/lib.rs                              | 5 +----
 src/test/rustdoc-ui/issue-61732.rs                       | 2 +-
 src/test/rustdoc-ui/issue-61732.stderr                   | 8 ++++----
 .../keyword/extern/keyword-extern-as-identifier-use.rs   | 1 +
 .../extern/keyword-extern-as-identifier-use.stderr       | 9 ++++++++-
 src/test/ui/resolve/raw-ident-in-path.rs                 | 5 +++++
 src/test/ui/resolve/raw-ident-in-path.stderr             | 9 +++++++++
 7 files changed, 29 insertions(+), 10 deletions(-)
 create mode 100644 src/test/ui/resolve/raw-ident-in-path.rs
 create mode 100644 src/test/ui/resolve/raw-ident-in-path.stderr

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 948b86225f38b..02ac560093d04 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2183,11 +2183,8 @@ impl<'a> Resolver<'a> {
                                     Applicability::MaybeIncorrect,
                                 )),
                             )
-                        } else if !ident.is_reserved() {
-                            (format!("maybe a missing crate `{}`?", ident), None)
                         } else {
-                            // the parser will already have complained about the keyword being used
-                            return PathResult::NonModule(PartialRes::new(Res::Err));
+                            (format!("maybe a missing crate `{}`?", ident), None)
                         }
                     } else if i == 0 {
                         (format!("use of undeclared type or module `{}`", ident), None)
diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs
index d4835c092248e..4bd8efeaa3b97 100644
--- a/src/test/rustdoc-ui/issue-61732.rs
+++ b/src/test/rustdoc-ui/issue-61732.rs
@@ -1,4 +1,4 @@
 // This previously triggered an ICE.
 
 pub(in crate::r#mod) fn main() {}
-//~^ ERROR expected module, found unresolved item
+//~^ ERROR failed to resolve: maybe a missing crate `r#mod`
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
index 6c8ba48864df0..8213422491120 100644
--- a/src/test/rustdoc-ui/issue-61732.stderr
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -1,11 +1,11 @@
-error[E0577]: expected module, found unresolved item `crate::r#mod`
-  --> $DIR/issue-61732.rs:3:8
+error[E0433]: failed to resolve: maybe a missing crate `r#mod`?
+  --> $DIR/issue-61732.rs:3:15
    |
 LL | pub(in crate::r#mod) fn main() {}
-   |        ^^^^^^^^^^^^ not a module
+   |               ^^^^^ maybe a missing crate `r#mod`?
 
 error: Compilation failed, aborting rustdoc
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0577`.
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
index b07de3e341c41..a46ce67d40d5a 100644
--- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
@@ -1,3 +1,4 @@
 use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+                 //~| ERROR unresolved import `r#extern`
 
 fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
index 05802f2d36710..edbb36452b6ce 100644
--- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers
 LL | use r#extern::foo;
    |     ^^^^^^^^
 
-error: aborting due to previous error
+error[E0432]: unresolved import `r#extern`
+  --> $DIR/keyword-extern-as-identifier-use.rs:1:5
+   |
+LL | use extern::foo;
+   |     ^^^^^^ maybe a missing crate `r#extern`?
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs
new file mode 100644
index 0000000000000..1bcbef5943741
--- /dev/null
+++ b/src/test/ui/resolve/raw-ident-in-path.rs
@@ -0,0 +1,5 @@
+// Regression test for issue #63882.
+
+type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate`
+
+fn main() {}
diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr
new file mode 100644
index 0000000000000..f2efcbc8e8586
--- /dev/null
+++ b/src/test/ui/resolve/raw-ident-in-path.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `r#break` in module `crate`
+  --> $DIR/raw-ident-in-path.rs:3:17
+   |
+LL | type A = crate::r#break;
+   |                 ^^^^^^^ not found in `crate`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.

From 81099c27ddc856238d7b1b15c20d487130ef3057 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 10 Mar 2020 10:10:10 +0100
Subject: [PATCH 08/12] VariantSizeDifferences: bail on SizeOverflow

---
 src/librustc_lint/types.rs                             |  6 ++----
 .../ui/lint/issue-69485-var-size-diffs-too-large.rs    | 10 ++++++++++
 .../lint/issue-69485-var-size-diffs-too-large.stderr   |  8 ++++++++
 3 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
 create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr

diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 86d93612e993b..2896682ea8268 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -998,10 +998,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
             let ty = cx.tcx.erase_regions(&t);
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
-                Err(ty::layout::LayoutError::Unknown(_)) => return,
-                Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
-                    bug!("failed to get layout for `{}`: {}", t, err);
-                }
+                Err(ty::layout::LayoutError::Unknown(_))
+                | Err(ty::layout::LayoutError::SizeOverflow(_)) => return,
             };
             let (variants, tag) = match layout.variants {
                 layout::Variants::Multiple {
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
new file mode 100644
index 0000000000000..49d489d916837
--- /dev/null
+++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
@@ -0,0 +1,10 @@
+// build-fail
+// only-x86_64
+
+fn main() {
+    Bug::V([0; !0]); //~ ERROR is too big for the current
+}
+
+enum Bug {
+    V([u8; !0]),
+}
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr
new file mode 100644
index 0000000000000..d31ce9cfe0c2b
--- /dev/null
+++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr
@@ -0,0 +1,8 @@
+error: the type `[u8; 18446744073709551615]` is too big for the current architecture
+  --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12
+   |
+LL |     Bug::V([0; !0]);
+   |            ^^^^^^^
+
+error: aborting due to previous error
+

From f53f9a88f16dc3d1b94ed2e7f0f201e1456d8cfc Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sun, 15 Mar 2020 19:43:25 +0100
Subject: [PATCH 09/12] Bump the bootstrap compiler

---
 src/bootstrap/builder.rs                   | 10 ++----
 src/bootstrap/channel.rs                   |  2 +-
 src/liballoc/boxed.rs                      | 24 -------------
 src/libcore/cell.rs                        |  2 +-
 src/libcore/lib.rs                         |  2 +-
 src/libcore/ops/generator.rs               | 31 ++---------------
 src/librustc_data_structures/box_region.rs | 39 ----------------------
 src/libstd/future.rs                       |  5 +--
 src/stage0.txt                             |  2 +-
 9 files changed, 9 insertions(+), 108 deletions(-)

diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e4b57cddfb891..602e4511ea583 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -725,7 +725,7 @@ impl<'a> Builder<'a> {
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile");
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
 
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
@@ -847,13 +847,7 @@ impl<'a> Builder<'a> {
             rustflags.arg("-Zforce-unstable-if-unmarked");
         }
 
-        // cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace`
-        // to `-Zmacro-backtrace`, keep only the latter after beta promotion.
-        if stage == 0 {
-            rustflags.arg("-Zexternal-macro-backtrace");
-        } else {
-            rustflags.arg("-Zmacro-backtrace");
-        }
+        rustflags.arg("-Zmacro-backtrace");
 
         let want_rustdoc = self.doc_tests != DocTests::No;
 
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 504cba45570c1..be2b0f36d14a7 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -13,7 +13,7 @@ use build_helper::output;
 use crate::Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.43.0";
+pub const CFG_RELEASE_NUM: &str = "1.44.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 9a7d0d9aebaaf..36641284a769b 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -1105,29 +1105,6 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Box<T> {}
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
     type Yield = G::Yield;
@@ -1138,7 +1115,6 @@ impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
     type Yield = G::Yield;
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 9ebb317641875..a84f0caf0a0c3 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1538,7 +1538,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303.
+#[repr(no_niche)] // rust-lang/rust#68303.
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a1dde1d51ef80..5a731766054bd 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -140,7 +140,7 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303
+#![feature(no_niche)] // rust-lang/rust#68303
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs
index 4e43561996c37..4f23620b92b80 100644
--- a/src/libcore/ops/generator.rs
+++ b/src/libcore/ops/generator.rs
@@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
 #[lang = "generator"]
 #[unstable(feature = "generator_trait", issue = "43122")]
 #[fundamental]
-pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
+pub trait Generator<R = ()> {
     /// The type of value this generator yields.
     ///
     /// This associated type corresponds to the `yield` expression and the
@@ -110,35 +110,9 @@ pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
     /// been returned previously. While generator literals in the language are
     /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
     /// for all implementations of the `Generator` trait.
-    fn resume(
-        self: Pin<&mut Self>,
-        #[cfg(not(bootstrap))] arg: R,
-    ) -> GeneratorState<Self::Yield, Self::Return>;
+    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
 }
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
     type Yield = G::Yield;
@@ -149,7 +123,6 @@ impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
     type Yield = G::Yield;
diff --git a/src/librustc_data_structures/box_region.rs b/src/librustc_data_structures/box_region.rs
index dbc54291f4087..edeb4f83c7d7e 100644
--- a/src/librustc_data_structures/box_region.rs
+++ b/src/librustc_data_structures/box_region.rs
@@ -25,22 +25,6 @@ pub struct PinnedGenerator<I, A, R> {
 }
 
 impl<I, A, R> PinnedGenerator<I, A, R> {
-    #[cfg(bootstrap)]
-    pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
-        generator: T,
-    ) -> (I, Self) {
-        let mut result = PinnedGenerator { generator: Box::pin(generator) };
-
-        // Run it to the first yield to set it up
-        let init = match Pin::new(&mut result.generator).resume() {
-            GeneratorState::Yielded(YieldType::Initial(y)) => y,
-            _ => panic!(),
-        };
-
-        (init, result)
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
         generator: T,
     ) -> (I, Self) {
@@ -55,19 +39,6 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
         (init, result)
     }
 
-    #[cfg(bootstrap)]
-    pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
-        BOX_REGION_ARG.with(|i| {
-            i.set(Action::Access(AccessAction(closure)));
-        });
-
-        // Call the generator, which in turn will call the closure in BOX_REGION_ARG
-        if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume() {
-            panic!()
-        }
-    }
-
-    #[cfg(not(bootstrap))]
     pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
         BOX_REGION_ARG.with(|i| {
             i.set(Action::Access(AccessAction(closure)));
@@ -79,16 +50,6 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
         }
     }
 
-    #[cfg(bootstrap)]
-    pub fn complete(&mut self) -> R {
-        // Tell the generator we want it to complete, consuming it and yielding a result
-        BOX_REGION_ARG.with(|i| i.set(Action::Complete));
-
-        let result = Pin::new(&mut self.generator).resume();
-        if let GeneratorState::Complete(r) = result { r } else { panic!() }
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn complete(&mut self) -> R {
         // Tell the generator we want it to complete, consuming it and yielding a result
         BOX_REGION_ARG.with(|i| i.set(Action::Complete));
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 7b1beb1ecda80..c1ca6771326cb 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -41,10 +41,7 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
         let _guard = unsafe { set_task_context(cx) };
-        match gen.resume(
-            #[cfg(not(bootstrap))]
-            (),
-        ) {
+        match gen.resume(()) {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         }
diff --git a/src/stage0.txt b/src/stage0.txt
index 55416b6729adb..4d9a91e38b33c 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2020-02-29
+date: 2020-03-12
 rustc: beta
 cargo: beta
 

From ce5e49f86fc8bff241695f8a62e77f517749bd6d Mon Sep 17 00:00:00 2001
From: lzutao <taolzu@gmail.com>
Date: Mon, 16 Mar 2020 23:43:42 +0700
Subject: [PATCH 10/12] Use sublice patterns to avoid computing the len

---
 src/libstd/sys_common/wtf8.rs | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 7509e1ee35dee..77977e255172a 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -599,24 +599,16 @@ impl Wtf8 {
 
     #[inline]
     fn final_lead_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match self.bytes[(len - 3)..] {
-            [0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)),
             _ => None,
         }
     }
 
     #[inline]
     fn initial_trail_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match self.bytes[..3] {
-            [0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)),
             _ => None,
         }
     }

From e1bc9af9eb503e7ca0027b4d7086c35cd661140e Mon Sep 17 00:00:00 2001
From: lzutao <taolzu@gmail.com>
Date: Mon, 16 Mar 2020 23:54:32 +0700
Subject: [PATCH 11/12] Fix wrong deref

---
 src/libstd/sys_common/wtf8.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 77977e255172a..498950e682101 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -600,7 +600,7 @@ impl Wtf8 {
     #[inline]
     fn final_lead_surrogate(&self) -> Option<u16> {
         match self.bytes {
-            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)),
+            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }
@@ -608,7 +608,7 @@ impl Wtf8 {
     #[inline]
     fn initial_trail_surrogate(&self) -> Option<u16> {
         match self.bytes {
-            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)),
+            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }

From 7894509b000157185b10cfae64ac1e88acd88f4a Mon Sep 17 00:00:00 2001
From: Oliver Scherer <github35764891676564198441@oli-obk.de>
Date: Mon, 16 Mar 2020 18:51:55 +0100
Subject: [PATCH 12/12] Fiddle `ParamEnv` through to a place that used to use
 `ParamEnv::empty` in a buggy manner

---
 src/librustc/ty/inhabitedness/mod.rs          | 49 +++++++++++++------
 src/librustc_lint/unused.rs                   |  7 ++-
 .../build/matches/simplify.rs                 |  7 ++-
 src/librustc_mir_build/hair/pattern/_match.rs |  4 +-
 src/librustc_passes/liveness.rs               | 21 ++++++--
 5 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 144e3bc9c8bc6..b166c4dea0c85 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> {
     /// ```
     /// This code should only compile in modules where the uninhabitedness of Foo is
     /// visible.
-    pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
+    pub fn is_ty_uninhabited_from(
+        self,
+        module: DefId,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
         // To check whether this type is uninhabited at all (not just from the
         // given node), you could check whether the forest is empty.
         // ```
         // forest.is_empty()
         // ```
-        ty.uninhabited_from(self).contains(self, module)
+        ty.uninhabited_from(self, param_env).contains(self, module)
     }
 
-    pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
-        !ty.uninhabited_from(self).is_empty()
+    pub fn is_ty_uninhabited_from_any_module(
+        self,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        !ty.uninhabited_from(self, param_env).is_empty()
     }
 }
 
 impl<'tcx> AdtDef {
     /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest {
+    fn uninhabited_from(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        substs: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> DefIdForest {
         // Non-exhaustive ADTs from other crates are always considered inhabited.
         if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
             DefIdForest::empty()
         } else {
             DefIdForest::intersection(
                 tcx,
-                self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())),
+                self.variants
+                    .iter()
+                    .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
             )
         }
     }
@@ -126,6 +142,7 @@ impl<'tcx> VariantDef {
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         adt_kind: AdtKind,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
         let is_enum = match adt_kind {
             // For now, `union`s are never considered uninhabited.
@@ -140,7 +157,7 @@ impl<'tcx> VariantDef {
         } else {
             DefIdForest::union(
                 tcx,
-                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)),
+                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
             )
         }
     }
@@ -153,8 +170,9 @@ impl<'tcx> FieldDef {
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         is_enum: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
-        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx);
+        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
         // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
         // `Visibility::Invisible` so we need to override `self.vis` if we're
         // dealing with an enum.
@@ -176,20 +194,21 @@ impl<'tcx> FieldDef {
 
 impl<'tcx> TyS<'tcx> {
     /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest {
+    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
         match self.kind {
-            Adt(def, substs) => def.uninhabited_from(tcx, substs),
+            Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
 
             Never => DefIdForest::full(tcx),
 
-            Tuple(ref tys) => {
-                DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx)))
-            }
+            Tuple(ref tys) => DefIdForest::union(
+                tcx,
+                tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
+            ),
 
-            Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+            Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
                 // If the array is definitely non-empty, it's uninhabited if
                 // the type of its elements is uninhabited.
-                Some(n) if n != 0 => ty.uninhabited_from(tcx),
+                Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
                 _ => DefIdForest::empty(),
             },
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index d0bbc5ac26d89..2ac461a0eb264 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
             descr_post: &str,
             plural_len: usize,
         ) -> bool {
-            if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty)
+            if ty.is_unit()
+                || cx.tcx.is_ty_uninhabited_from(
+                    cx.tcx.parent_module(expr.hir_id),
+                    ty,
+                    cx.param_env,
+                )
             {
                 return true;
             }
diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
index 80fa0c44860e4..aea4f5f1b3ac9 100644
--- a/src/librustc_mir_build/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     i == variant_index || {
                         self.hir.tcx().features().exhaustive_patterns
                             && !v
-                                .uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind())
+                                .uninhabited_from(
+                                    self.hir.tcx(),
+                                    substs,
+                                    adt_def.adt_kind(),
+                                    self.hir.param_env,
+                                )
                                 .is_empty()
                     }
                 }) && (adt_def.did.is_local()
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 37ad5f5ea4e38..486dd3579d293 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -598,7 +598,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         if self.tcx.features().exhaustive_patterns {
-            self.tcx.is_ty_uninhabited_from(self.module, ty)
+            self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
         } else {
             false
         }
@@ -1267,7 +1267,7 @@ fn all_constructors<'a, 'tcx>(
                 def.variants
                     .iter()
                     .filter(|v| {
-                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
                             .contains(cx.tcx, cx.module)
                     })
                     .map(|v| Variant(v.def_id))
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 030d0893b0274..d7208a00e0938 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -398,7 +398,7 @@ fn visit_fn<'tcx>(
     intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
 
     // compute liveness
-    let mut lsets = Liveness::new(&mut fn_maps, body_id);
+    let mut lsets = Liveness::new(&mut fn_maps, def_id);
     let entry_ln = lsets.compute(&body.value);
 
     // check for various error conditions
@@ -658,6 +658,7 @@ const ACC_USE: u32 = 4;
 struct Liveness<'a, 'tcx> {
     ir: &'a mut IrMaps<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     s: Specials,
     successors: Vec<LiveNode>,
     rwu_table: RWUTable,
@@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
-    fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
+    fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> {
         // Special nodes and variables:
         // - exit_ln represents the end of the fn, either by return or panic
         // - implicit_ret_var is a pseudo-variable that represents
@@ -681,7 +682,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             clean_exit_var: ir.add_variable(CleanExit),
         };
 
-        let tables = ir.tcx.body_tables(body);
+        let tables = ir.tcx.typeck_tables_of(def_id);
+        let param_env = ir.tcx.param_env(def_id);
 
         let num_live_nodes = ir.num_live_nodes;
         let num_vars = ir.num_vars;
@@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         Liveness {
             ir,
             tables,
+            param_env,
             s: specials,
             successors: vec![invalid_node(); num_live_nodes],
             rwu_table: RWUTable::new(num_live_nodes * num_vars),
@@ -1126,7 +1129,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             hir::ExprKind::Call(ref f, ref args) => {
                 let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ
@@ -1137,7 +1144,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             hir::ExprKind::MethodCall(.., ref args) => {
                 let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ