about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-10-12 00:20:34 +0000
committerbors <bors@rust-lang.org>2021-10-12 00:20:34 +0000
commit97e3b30285af8526f8d21072a0c6d3f231e74876 (patch)
tree4ac047b9f4927369c428718b86c233ab4830c505
parent7cc8c44871b6e789d29fc0d42dacad9804c3a41c (diff)
parentf94a325496a475ec866f41a8036d4a418832522c (diff)
downloadrust-97e3b30285af8526f8d21072a0c6d3f231e74876.tar.gz
rust-97e3b30285af8526f8d21072a0c6d3f231e74876.zip
Auto merge of #89791 - matthiaskrgr:rollup-1lhxh5b, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #89471 (Use Ancestory to check default fn in const impl instead of comparing idents)
 - #89643 (Fix inherent impl overlap check.)
 - #89651 (Add `Poll::ready` and revert stabilization of `task::ready!`)
 - #89675 (Re-use TypeChecker instead of passing around some of its fields )
 - #89710 (Add long explanation for error E0482)
 - #89756 (Greatly reduce amount of debuginfo compiled for bootstrap itself)
 - #89760 (Remove hack ignoring unused attributes for stage 0 std)
 - #89772 (Fix function-names test for GDB 10.1)
 - #89785 (Fix ICE when compiling nightly std/rustc on beta compiler)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.toml9
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs22
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs112
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0482.md73
-rw-r--r--compiler/rustc_index/src/vec.rs6
-rw-r--r--compiler/rustc_passes/src/check_const.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs103
-rw-r--r--compiler/rustc_typeck/src/lib.rs1
-rw-r--r--library/core/src/marker.rs3
-rw-r--r--library/core/src/task/mod.rs4
-rw-r--r--library/core/src/task/poll.rs33
-rw-r--r--library/core/src/task/ready.rs62
-rw-r--r--src/bootstrap/bootstrap.py3
-rw-r--r--src/bootstrap/builder.rs6
-rw-r--r--src/test/debuginfo/function-names.rs31
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs (renamed from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs)6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr (renamed from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr)6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs34
-rw-r--r--src/tools/tidy/src/error_codes_check.rs2
22 files changed, 385 insertions, 183 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 42dd5d7ef43..8d6afd2b448 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -89,6 +89,15 @@ gimli.debug = 0
 miniz_oxide.debug = 0
 object.debug = 0
 
+# The only package that ever uses debug builds is bootstrap.
+# We care a lot about bootstrap's compile times, so don't include debug info for
+# dependencies, only bootstrap itself.
+[profile.dev]
+debug = 0
+[profile.dev.package]
+# Only use debuginfo=1 to further reduce compile times.
+bootstrap.debug = 1
+
 # We want the RLS to use the version of Cargo that we've got vendored in this
 # repository to ensure that the same exact version of Cargo is used by both the
 # RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository
diff --git a/RELEASES.md b/RELEASES.md
index ef1377a4a32..269740c171c 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -64,7 +64,6 @@ Stabilised APIs
 - [`VecDeque::shrink_to`]
 - [`HashMap::shrink_to`]
 - [`HashSet::shrink_to`]
-- [`task::ready!`]
 
 These APIs are now usable in const contexts:
 
@@ -128,7 +127,6 @@ and related tools.
 [`VecDeque::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.shrink_to
 [`HashMap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.shrink_to
 [`HashSet::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html#method.shrink_to
-[`task::ready!`]: https://doc.rust-lang.org/stable/std/task/macro.ready.html
 [`std::mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
 [`slice::first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first
 [`slice::split_first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 55790bd2daa..07eadce1773 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1153,28 +1153,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         .convert_all(data);
     }
 
-    /// Convenient wrapper around `relate_tys::relate_types` -- see
-    /// that fn for docs.
-    fn relate_types(
-        &mut self,
-        a: Ty<'tcx>,
-        v: ty::Variance,
-        b: Ty<'tcx>,
-        locations: Locations,
-        category: ConstraintCategory,
-    ) -> Fallible<()> {
-        relate_tys::relate_types(
-            self.infcx,
-            self.param_env,
-            a,
-            v,
-            b,
-            locations,
-            category,
-            self.borrowck_context,
-        )
-    }
-
     /// Try to relate `sub <: sup`
     fn sub_types(
         &mut self,
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index b788529dc1c..415d1abaa8b 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,5 +1,5 @@
 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
+use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Const, Ty};
@@ -7,48 +7,38 @@ use rustc_trait_selection::traits::query::Fallible;
 
 use crate::constraints::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
-use crate::type_check::{BorrowCheckContext, Locations};
-
-/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
-///
-/// - "Covariant" `a <: b`
-/// - "Invariant" `a == b`
-/// - "Contravariant" `a :> b`
-///
-/// N.B., the type `a` is permitted to have unresolved inference
-/// variables, but not the type `b`.
-#[instrument(skip(infcx, param_env, borrowck_context), level = "debug")]
-pub(super) fn relate_types<'tcx>(
-    infcx: &InferCtxt<'_, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    a: Ty<'tcx>,
-    v: ty::Variance,
-    b: Ty<'tcx>,
-    locations: Locations,
-    category: ConstraintCategory,
-    borrowck_context: &mut BorrowCheckContext<'_, 'tcx>,
-) -> Fallible<()> {
-    TypeRelating::new(
-        infcx,
-        NllTypeRelatingDelegate::new(
-            infcx,
-            borrowck_context,
-            param_env,
-            locations,
-            category,
-            UniverseInfo::relate(a, b),
-        ),
-        v,
-    )
-    .relate(a, b)?;
-    Ok(())
+use crate::type_check::{Locations, TypeChecker};
+
+impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
+    ///
+    /// - "Covariant" `a <: b`
+    /// - "Invariant" `a == b`
+    /// - "Contravariant" `a :> b`
+    ///
+    /// N.B., the type `a` is permitted to have unresolved inference
+    /// variables, but not the type `b`.
+    #[instrument(skip(self), level = "debug")]
+    pub(super) fn relate_types(
+        &mut self,
+        a: Ty<'tcx>,
+        v: ty::Variance,
+        b: Ty<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory,
+    ) -> Fallible<()> {
+        TypeRelating::new(
+            self.infcx,
+            NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
+            v,
+        )
+        .relate(a, b)?;
+        Ok(())
+    }
 }
 
 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
-    infcx: &'me InferCtxt<'me, 'tcx>,
-    borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>,
-
-    param_env: ty::ParamEnv<'tcx>,
+    type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
 
     /// Where (and why) is this relation taking place?
     locations: Locations,
@@ -63,25 +53,24 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
 
 impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
     fn new(
-        infcx: &'me InferCtxt<'me, 'tcx>,
-        borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
         locations: Locations,
         category: ConstraintCategory,
         universe_info: UniverseInfo<'tcx>,
     ) -> Self {
-        Self { infcx, borrowck_context, param_env, locations, category, universe_info }
+        Self { type_checker, locations, category, universe_info }
     }
 }
 
 impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+        self.type_checker.param_env
     }
 
     fn create_next_universe(&mut self) -> ty::UniverseIndex {
-        let universe = self.infcx.create_next_universe();
-        self.borrowck_context
+        let universe = self.type_checker.infcx.create_next_universe();
+        self.type_checker
+            .borrowck_context
             .constraints
             .universe_causes
             .insert(universe, self.universe_info.clone());
@@ -90,15 +79,18 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
 
     fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
         let origin = NllRegionVariableOrigin::Existential { from_forall };
-        self.infcx.next_nll_region_var(origin)
+        self.type_checker.infcx.next_nll_region_var(origin)
     }
 
     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        self.borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
+        self.type_checker
+            .borrowck_context
+            .constraints
+            .placeholder_region(self.type_checker.infcx, placeholder)
     }
 
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
-        self.infcx.next_nll_region_var_in_universe(
+        self.type_checker.infcx.next_nll_region_var_in_universe(
             NllRegionVariableOrigin::Existential { from_forall: false },
             universe,
         )
@@ -110,15 +102,17 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
         sub: ty::Region<'tcx>,
         info: ty::VarianceDiagInfo<'tcx>,
     ) {
-        let sub = self.borrowck_context.universal_regions.to_region_vid(sub);
-        let sup = self.borrowck_context.universal_regions.to_region_vid(sup);
-        self.borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint {
-            sup,
-            sub,
-            locations: self.locations,
-            category: self.category,
-            variance_info: info,
-        });
+        let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
+        let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
+        self.type_checker.borrowck_context.constraints.outlives_constraints.push(
+            OutlivesConstraint {
+                sup,
+                sub,
+                locations: self.locations,
+                category: self.category,
+                variance_info: info,
+            },
+        );
     }
 
     // We don't have to worry about the equality of consts during borrow checking
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 45d91c2047d..1b4b58314b3 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -242,6 +242,7 @@ E0468: include_str!("./error_codes/E0468.md"),
 E0469: include_str!("./error_codes/E0469.md"),
 E0477: include_str!("./error_codes/E0477.md"),
 E0478: include_str!("./error_codes/E0478.md"),
+E0482: include_str!("./error_codes/E0482.md"),
 E0491: include_str!("./error_codes/E0491.md"),
 E0492: include_str!("./error_codes/E0492.md"),
 E0493: include_str!("./error_codes/E0493.md"),
@@ -599,7 +600,6 @@ E0785: include_str!("./error_codes/E0785.md"),
 //  E0479, // the type `..` (provided as the value of a type parameter) is...
 //  E0480, // lifetime of method receiver does not outlive the method call
 //  E0481, // lifetime of function argument does not outlive the function call
-    E0482, // lifetime of return value does not outlive the function call
 //  E0483, // lifetime of operand does not outlive the operation
 //  E0484, // reference is not valid at the time of borrow
 //  E0485, // automatically reference is not valid at the time of borrow
diff --git a/compiler/rustc_error_codes/src/error_codes/E0482.md b/compiler/rustc_error_codes/src/error_codes/E0482.md
new file mode 100644
index 00000000000..58ebf43cc98
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0482.md
@@ -0,0 +1,73 @@
+A lifetime of a returned value does not outlive the function call.
+
+Erroneous code example:
+
+```compile_fail,E0482
+fn prefix<'a>(
+    words: impl Iterator<Item = &'a str>
+) -> impl Iterator<Item = String> { // error!
+    words.map(|v| format!("foo-{}", v))
+}
+```
+
+To fix this error, make the lifetime of the returned value explicit:
+
+```
+fn prefix<'a>(
+    words: impl Iterator<Item = &'a str> + 'a
+) -> impl Iterator<Item = String> + 'a { // ok!
+    words.map(|v| format!("foo-{}", v))
+}
+```
+
+The [`impl Trait`] feature in this example uses an implicit `'static` lifetime
+restriction in the returned type. However the type implementing the `Iterator`
+passed to the function lives just as long as `'a`, which is not long enough.
+
+The solution involves adding lifetime bound to both function argument and
+the return value to make sure that the values inside the iterator
+are not dropped when the function goes out of the scope.
+
+An alternative solution would be to guarantee that the `Item` references
+in the iterator are alive for the whole lifetime of the program.
+
+```
+fn prefix(
+    words: impl Iterator<Item = &'static str>
+) -> impl Iterator<Item = String> {  // ok!
+    words.map(|v| format!("foo-{}", v))
+}
+```
+
+A similar lifetime problem might arise when returning closures:
+
+```compile_fail,E0482
+fn foo(
+    x: &mut Vec<i32>
+) -> impl FnMut(&mut Vec<i32>) -> &[i32] { // error!
+    |y| {
+        y.append(x);
+        y
+    }
+}
+```
+
+Analogically, a solution here is to use explicit return lifetime
+and move the ownership of the variable to the closure.
+
+```
+fn foo<'a>(
+    x: &'a mut Vec<i32>
+) -> impl FnMut(&mut Vec<i32>) -> &[i32] + 'a { // ok!
+    move |y| {
+        y.append(x);
+        y
+    }
+}
+```
+
+To better understand the lifetime treatment in the [`impl Trait`],
+please see the [RFC 1951].
+
+[`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html
+[RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index e9efa2f255d..69578e85f27 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -738,6 +738,12 @@ impl<I: Idx, T> IndexVec<I, Option<T>> {
         self.ensure_contains_elem(index, || None);
         self[index].get_or_insert_with(value)
     }
+
+    #[inline]
+    pub fn remove(&mut self, index: I) -> Option<T> {
+        self.ensure_contains_elem(index, || None);
+        self[index].take()
+    }
 }
 
 impl<I: Idx, T: Clone> IndexVec<I, T> {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 4a82252a32b..a0ceb567f25 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -8,7 +8,6 @@
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
 use rustc_attr as attr;
-use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -83,30 +82,39 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
         let _: Option<_> = try {
             if let hir::ItemKind::Impl(ref imp) = item.kind {
                 if let hir::Constness::Const = imp.constness {
-                    let did = imp.of_trait.as_ref()?.trait_def_id()?;
-                    let mut to_implement = FxHashSet::default();
-
-                    for did in self.tcx.associated_item_def_ids(did) {
+                    let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?;
+                    let ancestors = self
+                        .tcx
+                        .trait_def(trait_def_id)
+                        .ancestors(self.tcx, item.def_id.to_def_id())
+                        .ok()?;
+                    let mut to_implement = Vec::new();
+
+                    for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
+                    {
                         if let ty::AssocItem {
                             kind: ty::AssocKind::Fn, ident, defaultness, ..
-                        } = self.tcx.associated_item(*did)
+                        } = trait_item
                         {
                             // we can ignore functions that do not have default bodies:
                             // if those are unimplemented it will be catched by typeck.
-                            if defaultness.has_value()
-                                && !self.tcx.has_attr(*did, sym::default_method_body_is_const)
+                            if !defaultness.has_value()
+                                || self
+                                    .tcx
+                                    .has_attr(trait_item.def_id, sym::default_method_body_is_const)
                             {
-                                to_implement.insert(ident);
+                                continue;
                             }
-                        }
-                    }
 
-                    for it in imp
-                        .items
-                        .iter()
-                        .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. }))
-                    {
-                        to_implement.remove(&it.ident);
+                            let is_implemented = ancestors
+                                .leaf_def(self.tcx, trait_item.ident, trait_item.kind)
+                                .map(|node_item| !node_item.defining_node.is_from_trait())
+                                .unwrap_or(false);
+
+                            if !is_implemented {
+                                to_implement.push(ident.to_string());
+                            }
+                        }
                     }
 
                     // all nonconst trait functions (not marked with #[default_method_body_is_const])
@@ -118,7 +126,7 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
                                 item.span,
                                 "const trait implementations may not use non-const default functions",
                             )
-                            .note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::<Vec<_>>().join("`, `")))
+                            .note(&format!("`{}` not implemented", to_implement.join("`, `")))
                             .emit();
                     }
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index a73d2285d45..1a8f863952e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -704,7 +704,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
                 .collect();
 
-        never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::Send).unwrap());
+        if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
+            never_suggest_borrow.push(def_id);
+        }
 
         let param_env = obligation.param_env;
         let trait_ref = poly_trait_ref.skip_binder();
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
index b5eb74f708d..0373035a09a 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
@@ -3,6 +3,7 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_index::vec::IndexVec;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Symbol;
 use rustc_trait_selection::traits::{self, SkipLeakCheck};
@@ -158,14 +159,18 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
                     // This is advantageous to running the algorithm over the
                     // entire graph when there are many connected regions.
 
+                    rustc_index::newtype_index! {
+                        pub struct RegionId {
+                            ENCODABLE = custom
+                        }
+                    }
                     struct ConnectedRegion {
                         idents: SmallVec<[Symbol; 8]>,
                         impl_blocks: FxHashSet<usize>,
                     }
-                    // Highest connected region id
-                    let mut highest_region_id = 0;
+                    let mut connected_regions: IndexVec<RegionId, _> = Default::default();
+                    // Reverse map from the Symbol to the connected region id.
                     let mut connected_region_ids = FxHashMap::default();
-                    let mut connected_regions = FxHashMap::default();
 
                     for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() {
                         if impl_items.len() == 0 {
@@ -173,7 +178,7 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
                         }
                         // First obtain a list of existing connected region ids
                         let mut idents_to_add = SmallVec::<[Symbol; 8]>::new();
-                        let ids = impl_items
+                        let mut ids = impl_items
                             .in_definition_order()
                             .filter_map(|item| {
                                 let entry = connected_region_ids.entry(item.ident.name);
@@ -184,62 +189,64 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
                                     None
                                 }
                             })
-                            .collect::<FxHashSet<usize>>();
-                        match ids.len() {
-                            0 | 1 => {
-                                let id_to_set = if ids.is_empty() {
-                                    // Create a new connected region
-                                    let region = ConnectedRegion {
+                            .collect::<SmallVec<[RegionId; 8]>>();
+                        // Sort the id list so that the algorithm is deterministic
+                        ids.sort_unstable();
+                        let ids = ids;
+                        match &ids[..] {
+                            // Create a new connected region
+                            [] => {
+                                let id_to_set = connected_regions.next_index();
+                                // Update the connected region ids
+                                for ident in &idents_to_add {
+                                    connected_region_ids.insert(*ident, id_to_set);
+                                }
+                                connected_regions.insert(
+                                    id_to_set,
+                                    ConnectedRegion {
                                         idents: idents_to_add,
                                         impl_blocks: std::iter::once(i).collect(),
-                                    };
-                                    connected_regions.insert(highest_region_id, region);
-                                    (highest_region_id, highest_region_id += 1).0
-                                } else {
-                                    // Take the only id inside the list
-                                    let id_to_set = *ids.iter().next().unwrap();
-                                    let region = connected_regions.get_mut(&id_to_set).unwrap();
-                                    region.impl_blocks.insert(i);
-                                    region.idents.extend_from_slice(&idents_to_add);
-                                    id_to_set
-                                };
-                                let (_id, region) = connected_regions.iter().next().unwrap();
+                                    },
+                                );
+                            }
+                            // Take the only id inside the list
+                            &[id_to_set] => {
+                                let region = connected_regions[id_to_set].as_mut().unwrap();
+                                region.impl_blocks.insert(i);
+                                region.idents.extend_from_slice(&idents_to_add);
                                 // Update the connected region ids
-                                for ident in region.idents.iter() {
+                                for ident in &idents_to_add {
                                     connected_region_ids.insert(*ident, id_to_set);
                                 }
                             }
-                            _ => {
-                                // We have multiple connected regions to merge.
-                                // In the worst case this might add impl blocks
-                                // one by one and can thus be O(n^2) in the size
-                                // of the resulting final connected region, but
-                                // this is no issue as the final step to check
-                                // for overlaps runs in O(n^2) as well.
-
-                                // Take the smallest id from the list
-                                let id_to_set = *ids.iter().min().unwrap();
-
-                                // Sort the id list so that the algorithm is deterministic
-                                let mut ids = ids.into_iter().collect::<SmallVec<[usize; 8]>>();
-                                ids.sort_unstable();
-
-                                let mut region = connected_regions.remove(&id_to_set).unwrap();
-                                region.idents.extend_from_slice(&idents_to_add);
+                            // We have multiple connected regions to merge.
+                            // In the worst case this might add impl blocks
+                            // one by one and can thus be O(n^2) in the size
+                            // of the resulting final connected region, but
+                            // this is no issue as the final step to check
+                            // for overlaps runs in O(n^2) as well.
+                            &[id_to_set, ..] => {
+                                let mut region = connected_regions.remove(id_to_set).unwrap();
                                 region.impl_blocks.insert(i);
+                                region.idents.extend_from_slice(&idents_to_add);
+                                // Update the connected region ids
+                                for ident in &idents_to_add {
+                                    connected_region_ids.insert(*ident, id_to_set);
+                                }
 
+                                // Remove other regions from ids.
                                 for &id in ids.iter() {
                                     if id == id_to_set {
                                         continue;
                                     }
-                                    let r = connected_regions.remove(&id).unwrap();
-                                    // Update the connected region ids
+                                    let r = connected_regions.remove(id).unwrap();
                                     for ident in r.idents.iter() {
                                         connected_region_ids.insert(*ident, id_to_set);
                                     }
                                     region.idents.extend_from_slice(&r.idents);
                                     region.impl_blocks.extend(r.impl_blocks);
                                 }
+
                                 connected_regions.insert(id_to_set, region);
                             }
                         }
@@ -254,16 +261,22 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
                             let avg = impls.len() / connected_regions.len();
                             let s = connected_regions
                                 .iter()
-                                .map(|r| r.1.impl_blocks.len() as isize - avg as isize)
+                                .flatten()
+                                .map(|r| r.impl_blocks.len() as isize - avg as isize)
                                 .map(|v| v.abs() as usize)
                                 .sum::<usize>();
                             s / connected_regions.len()
                         },
-                        connected_regions.iter().map(|r| r.1.impl_blocks.len()).max().unwrap()
+                        connected_regions
+                            .iter()
+                            .flatten()
+                            .map(|r| r.impl_blocks.len())
+                            .max()
+                            .unwrap()
                     );
                     // List of connected regions is built. Now, run the overlap check
                     // for each pair of impl blocks in the same connected region.
-                    for (_id, region) in connected_regions.into_iter() {
+                    for region in connected_regions.into_iter().flatten() {
                         let mut impl_blocks =
                             region.impl_blocks.into_iter().collect::<SmallVec<[usize; 8]>>();
                         impl_blocks.sort_unstable();
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 65eedd2daaf..971776c882a 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
 #![feature(in_band_lifetimes)]
 #![feature(is_sorted)]
 #![feature(iter_zip)]
+#![feature(min_specialization)]
 #![feature(nll)]
 #![feature(try_blocks)]
 #![feature(never_type)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 37446bafacb..e5c3fafe5f1 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -30,7 +30,8 @@ use crate::hash::Hasher;
 /// [arc]: ../../std/sync/struct.Arc.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
+#[cfg_attr(all(not(test), bootstrap), rustc_diagnostic_item = "send_trait")]
+#[cfg_attr(all(not(test), not(bootstrap)), rustc_diagnostic_item = "Send")]
 #[rustc_on_unimplemented(
     message = "`{Self}` cannot be sent between threads safely",
     label = "`{Self}` cannot be sent between threads safely"
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index 5f077f77bbc..71a67a2793a 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -11,5 +11,7 @@ mod wake;
 pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
 
 mod ready;
-#[stable(feature = "ready_macro", since = "1.56.0")]
+#[unstable(feature = "ready_macro", issue = "70922")]
 pub use ready::ready;
+#[unstable(feature = "poll_ready", issue = "89780")]
+pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 57416aeb701..3e0b3e89758 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -3,6 +3,7 @@
 use crate::convert;
 use crate::ops::{self, ControlFlow};
 use crate::result::Result;
+use crate::task::Ready;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
@@ -92,6 +93,38 @@ impl<T> Poll<T> {
     pub const fn is_pending(&self) -> bool {
         !self.is_ready()
     }
+
+    /// Extracts the successful type of a [`Poll<T>`].
+    ///
+    /// When combined with the `?` operator, this function will
+    /// propogate any [`Poll::Pending`] values to the caller, and
+    /// extract the `T` from [`Poll::Ready`].
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(poll_ready)]
+    ///
+    /// use std::task::{Context, Poll};
+    /// use std::future::{self, Future};
+    /// use std::pin::Pin;
+    ///
+    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+    ///     let mut fut = future::ready(42);
+    ///     let fut = Pin::new(&mut fut);
+    ///
+    ///     let num = fut.poll(cx).ready()?;
+    ///     # drop(num);
+    ///     // ... use num
+    ///
+    ///     Poll::Ready(())
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "poll_ready", issue = "89780")]
+    pub fn ready(self) -> Ready<T> {
+        Ready(self)
+    }
 }
 
 impl<T, E> Poll<Result<T, E>> {
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index 2834ca5fe22..174ca675460 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,3 +1,8 @@
+use core::convert;
+use core::fmt;
+use core::ops::{ControlFlow, FromResidual, Try};
+use core::task::Poll;
+
 /// Extracts the successful type of a [`Poll<T>`].
 ///
 /// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -8,6 +13,8 @@
 /// # Examples
 ///
 /// ```
+/// #![feature(ready_macro)]
+///
 /// use std::task::{ready, Context, Poll};
 /// use std::future::{self, Future};
 /// use std::pin::Pin;
@@ -27,6 +34,7 @@
 /// The `ready!` call expands to:
 ///
 /// ```
+/// # #![feature(ready_macro)]
 /// # use std::task::{Context, Poll};
 /// # use std::future::{self, Future};
 /// # use std::pin::Pin;
@@ -45,7 +53,7 @@
 ///     # Poll::Ready(())
 /// # }
 /// ```
-#[stable(feature = "ready_macro", since = "1.56.0")]
+#[unstable(feature = "ready_macro", issue = "70922")]
 #[rustc_macro_transparency = "semitransparent"]
 pub macro ready($e:expr) {
     match $e {
@@ -55,3 +63,55 @@ pub macro ready($e:expr) {
         }
     }
 }
+
+/// Extracts the successful type of a [`Poll<T>`].
+///
+/// See [`Poll::ready`] for details.
+#[unstable(feature = "poll_ready", issue = "89780")]
+pub struct Ready<T>(pub(crate) Poll<T>);
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> Try for Ready<T> {
+    type Output = T;
+    type Residual = Ready<convert::Infallible>;
+
+    #[inline]
+    fn from_output(output: Self::Output) -> Self {
+        Ready(Poll::Ready(output))
+    }
+
+    #[inline]
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        match self.0 {
+            Poll::Ready(v) => ControlFlow::Continue(v),
+            Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> FromResidual for Ready<T> {
+    #[inline]
+    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+        match residual.0 {
+            Poll::Pending => Ready(Poll::Pending),
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
+    #[inline]
+    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+        match residual.0 {
+            Poll::Pending => Poll::Pending,
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "89780")]
+impl<T> fmt::Debug for Ready<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("Ready").finish()
+    }
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 817850b1ec7..1859130a7af 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -933,10 +933,9 @@ class RustBuild(object):
         env["LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \
             (os.pathsep + env["LIBRARY_PATH"]) \
             if "LIBRARY_PATH" in env else ""
+
         # preserve existing RUSTFLAGS
         env.setdefault("RUSTFLAGS", "")
-        env["RUSTFLAGS"] += " -Cdebuginfo=2"
-
         build_section = "target.{}".format(self.build)
         target_features = []
         if self.get_toml("crt-static", build_section) == "true":
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 1f2109879d1..7df7a36f540 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1342,12 +1342,6 @@ impl<'a> Builder<'a> {
                 rustdocflags.arg("-Dwarnings");
             }
 
-            // FIXME(#58633) hide "unused attribute" errors in incremental
-            // builds of the standard library, as the underlying checks are
-            // not yet properly integrated with incremental recompilation.
-            if mode == Mode::Std && compiler.stage == 0 && self.config.incremental {
-                lint_flags.push("-Aunused-attributes");
-            }
             // This does not use RUSTFLAGS due to caching issues with Cargo.
             // Clippy is treated as an "in tree" tool, but shares the same
             // cache as other "submodule" tools. With these options set in
diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs
index dec25bb4c20..61d5fc93cd2 100644
--- a/src/test/debuginfo/function-names.rs
+++ b/src/test/debuginfo/function-names.rs
@@ -9,36 +9,37 @@
 // gdb-command:info functions -q function_names::main
 // gdb-check:[...]static fn function_names::main();
 // gdb-command:info functions -q function_names::generic_func<*
-// gdb-check:[...]static fn function_names::generic_func(i32) -> i32;
+// gdb-check:[...]static fn function_names::generic_func<i32>(i32) -> i32;
 
 // Implementations
 // gdb-command:info functions -q function_names::.*::impl_function.*
-// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function();
+// gdb-check:[...]static fn function_names::GenericStruct<i32, i32>::impl_function<i32, i32>();
 // gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function();
 // gdb-check:[...]static fn function_names::TestStruct1::impl_function();
 
 // Trait implementations
 // gdb-command:info functions -q function_names::.*::trait_function.*
-// gdb-check:[...]static fn <function_names::GenericStruct<T,i32> as function_names::TestTrait1>::trait_function();
-// gdb-check:[...]static fn <function_names::GenericStruct<[T; N],f32> as function_names::TestTrait1>::trait_function();
-// gdb-check:[...]static fn <function_names::Mod1::TestStruct2 as function_names::Mod1::TestTrait2>::trait_function();
-// gdb-check:[...]static fn <function_names::TestStruct1 as function_names::TestTrait1>::trait_function();
+// gdb-check:[...]static fn function_names::Mod1::{impl#1}::trait_function();
+// gdb-check:[...]static fn function_names::{impl#1}::trait_function();
+// gdb-check:[...]static fn function_names::{impl#3}::trait_function<i32>();
+// gdb-check:[...]static fn function_names::{impl#5}::trait_function3<function_names::TestStruct1>();
+// gdb-check:[...]static fn function_names::{impl#6}::trait_function<i32, 1>();
 
 // Closure
-// gdb-command:info functions -q function_names::.*::{{closure.*
-// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0});
-// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0});
-// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0});
+// gdb-command:info functions -q function_names::.*::{closure.*
+// gdb-check:[...]static fn function_names::generic_func::{closure#0}<i32>(*mut function_names::generic_func::{closure#0});
+// gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure#0});
+// gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}<i32, i32>(*mut function_names::{impl#2}::impl_function::{closure#0});
 
 // Generator
 // Generators don't seem to appear in GDB's symbol table.
 
 // Const generic parameter
 // gdb-command:info functions -q function_names::const_generic_fn.*
-// gdb-check:[...]static fn function_names::const_generic_fn_bool();
-// gdb-check:[...]static fn function_names::const_generic_fn_non_int();
-// gdb-check:[...]static fn function_names::const_generic_fn_signed_int();
-// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int();
+// gdb-check:[...]static fn function_names::const_generic_fn_bool<false>();
+// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#fe3cfa0214ac55c7}>();
+// gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>();
+// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>();
 
 // === CDB TESTS ===================================================================================
 
@@ -103,7 +104,7 @@ fn main() {
     GenericStruct::<TestStruct1, usize>::trait_function3();
 
     // Generic function
-    let _ = generic_func(42);
+    let _ = generic_func(42i32);
 
     // Closure
     let closure = || { TestStruct1 };
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
index 59de9e95719..8eefb375b8c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
@@ -1,4 +1,5 @@
 #![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
 
 trait Tr {
     fn req(&self);
@@ -18,11 +19,6 @@ impl const Tr for S {
     fn req(&self) {}
 } //~^^ ERROR const trait implementations may not use non-const default functions
 
-impl const Tr for u8 {
-    fn req(&self) {}
-    fn prov(&self) {}
-}
-
 impl const Tr for u16 {
     fn prov(&self) {}
     fn default() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
index 5301e0ad12e..a0916797041 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
@@ -1,5 +1,5 @@
 error: const trait implementations may not use non-const default functions
-  --> $DIR/impl-with-default-fn.rs:17:1
+  --> $DIR/impl-with-default-fn-fail.rs:18:1
    |
 LL | / impl const Tr for S {
 LL | |     fn req(&self) {}
@@ -9,7 +9,7 @@ LL | | }
    = note: `prov` not implemented
 
 error: const trait implementations may not use non-const default functions
-  --> $DIR/impl-with-default-fn.rs:32:1
+  --> $DIR/impl-with-default-fn-fail.rs:28:1
    |
 LL | / impl const Tr for u32 {
 LL | |     fn req(&self) {}
@@ -20,7 +20,7 @@ LL | | }
    = note: `prov` not implemented
 
 error[E0046]: not all trait items implemented, missing: `req`
-  --> $DIR/impl-with-default-fn.rs:26:1
+  --> $DIR/impl-with-default-fn-fail.rs:22:1
    |
 LL |     fn req(&self);
    |     -------------- `req` from trait
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
new file mode 100644
index 00000000000..ba3fec0882b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
@@ -0,0 +1,34 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+trait Tr {
+    fn req(&self);
+
+    fn prov(&self) {
+        println!("lul");
+        self.req();
+    }
+
+    #[default_method_body_is_const]
+    fn default() {}
+}
+
+impl const Tr for u8 {
+    fn req(&self) {}
+    fn prov(&self) {}
+}
+
+macro_rules! impl_tr {
+    ($ty: ty) => {
+        impl const Tr for $ty {
+            fn req(&self) {}
+            fn prov(&self) {}
+        }
+    }
+}
+
+impl_tr!(u64);
+
+fn main() {}
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index 53c75a46339..ce169867b7b 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -11,7 +11,7 @@ use regex::Regex;
 // A few of those error codes can't be tested but all the others can and *should* be tested!
 const EXEMPTED_FROM_TEST: &[&str] = &[
     "E0227", "E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0464", "E0465", "E0476",
-    "E0482", "E0514", "E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
+    "E0514", "E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
 ];
 
 // Some error codes don't have any tests apparently...