about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-14 00:30:46 +0000
committerbors <bors@rust-lang.org>2023-03-14 00:30:46 +0000
commitc54af457d05722321ca88c2ae0e5706ef803c5fb (patch)
tree04c6c57d4f325d76ae7de556262bf908fbaf70df
parent22f247c6f3ed388cb702d01c2ff27da658a8b353 (diff)
parent30cd4b3a161d38574a599f2aa58db8334b470f8b (diff)
downloadrust-c54af457d05722321ca88c2ae0e5706ef803c5fb.tar.gz
rust-c54af457d05722321ca88c2ae0e5706ef803c5fb.zip
Auto merge of #109097 - matthiaskrgr:rollup-6ydc4ri, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #108419 (Stabilize `atomic_as_ptr`)
 - #108507 (use `as_ptr` to determine the address of atomics)
 - #108607 (Don't use fd-lock on Solaris in bootstrap)
 - #108830 (Treat projections with infer as placeholder during fast reject in new solver)
 - #109055 (create `config::tests::detect_src_and_out` test for bootstrap)
 - #109058 (Document BinOp::is_checkable)
 - #109081 (simd-wide-sum test: adapt for LLVM 17 codegen change)
 - #109083 (Update books)
 - #109088 (Gracefully handle `#[target_feature]` on statics)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs45
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs22
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs63
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs58
-rw-r--r--compiler/rustc_middle/src/ty/util.rs21
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs25
-rw-r--r--library/core/src/sync/atomic.rs13
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/hermit/futex.rs6
-rw-r--r--library/std/src/sys/hermit/mod.rs1
-rw-r--r--src/bootstrap/CHANGELOG.md1
-rw-r--r--src/bootstrap/Cargo.toml5
-rw-r--r--src/bootstrap/bin/main.rs17
-rw-r--r--src/bootstrap/config/tests.rs35
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--tests/codegen/simd-wide-sum.rs2
-rw-r--r--tests/ui/target-feature/invalid-attribute.rs35
-rw-r--r--tests/ui/target-feature/invalid-attribute.stderr95
-rw-r--r--tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs43
-rw-r--r--tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs15
-rw-r--r--tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr9
36 files changed, 451 insertions, 141 deletions
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8b6bf886b0d..f9bb8359208 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -61,25 +61,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
 
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
-    // In some cases, attribute are only valid on functions, but it's the `check_attr`
-    // pass that check that they aren't used anywhere else, rather this module.
-    // In these cases, we bail from performing further checks that are only meaningful for
-    // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
-    // report a delayed bug, just in case `check_attr` isn't doing its job.
-    let validate_fn_only_attr = |attr_sp| -> bool {
-        let def_kind = tcx.def_kind(did);
-        if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind {
-            true
-        } else {
-            tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions");
-            false
-        }
-    };
-
     let mut inline_span = None;
     let mut link_ordinal_span = None;
     let mut no_sanitize_span = None;
+
     for attr in attrs.iter() {
+        // In some cases, attribute are only valid on functions, but it's the `check_attr`
+        // pass that check that they aren't used anywhere else, rather this module.
+        // In these cases, we bail from performing further checks that are only meaningful for
+        // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
+        // report a delayed bug, just in case `check_attr` isn't doing its job.
+        let fn_sig = || {
+            use DefKind::*;
+
+            let def_kind = tcx.def_kind(did);
+            if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
+                Some(tcx.fn_sig(did))
+            } else {
+                tcx.sess
+                    .delay_span_bug(attr.span, "this attribute can only be applied to functions");
+                None
+            }
+        };
+
         if attr.has_name(sym::cold) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
         } else if attr.has_name(sym::rustc_allocator) {
@@ -169,8 +173,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                 }
             }
         } else if attr.has_name(sym::cmse_nonsecure_entry) {
-            if validate_fn_only_attr(attr.span)
-                && !matches!(tcx.fn_sig(did).skip_binder().abi(), abi::Abi::C { .. })
+            if let Some(fn_sig) = fn_sig()
+                && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
             {
                 struct_span_err!(
                     tcx.sess,
@@ -189,8 +193,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
         } else if attr.has_name(sym::track_caller) {
             if !tcx.is_closure(did.to_def_id())
-                && validate_fn_only_attr(attr.span)
-                && tcx.fn_sig(did).skip_binder().abi() != abi::Abi::Rust
+                && let Some(fn_sig) = fn_sig()
+                && fn_sig.skip_binder().abi() != abi::Abi::Rust
             {
                 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
                     .emit();
@@ -222,7 +226,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
             }
         } else if attr.has_name(sym::target_feature) {
             if !tcx.is_closure(did.to_def_id())
-                && tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal
+                && let Some(fn_sig) = fn_sig()
+                && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
             {
                 if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
                     // The `#[target_feature]` attribute is allowed on
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 02f3eeee0e7..07a33bcbb50 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -11,7 +11,7 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
-use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
+use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections};
 use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 
@@ -99,7 +99,12 @@ impl<'tcx> InherentCollect<'tcx> {
                 }
             }
 
-            if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
+            if let Some(simp) = simplify_type(
+                self.tcx,
+                self_ty,
+                TreatParams::AsCandidateKey,
+                TreatProjections::AsCandidateKey,
+            ) {
                 self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
             } else {
                 bug!("unexpected self type: {:?}", self_ty);
@@ -159,7 +164,12 @@ impl<'tcx> InherentCollect<'tcx> {
             }
         }
 
-        if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) {
+        if let Some(simp) = simplify_type(
+            self.tcx,
+            ty,
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        ) {
             self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
         } else {
             bug!("unexpected primitive type: {:?}", ty);
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 57805f7c800..562dd2caae3 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::middle::stability;
+use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
@@ -699,7 +700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     }
 
     fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
-        let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) else {
+        let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey) else {
             bug!("unexpected incoherent type: {:?}", self_ty)
         };
         for &impl_def_id in self.tcx.incoherent_impls(simp) {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 4b15e48bd27..7055d9257ec 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -25,6 +25,7 @@ use rustc_infer::infer::{
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
+use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
@@ -1257,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let target_ty = self
                 .autoderef(sugg_span, rcvr_ty)
                 .find(|(rcvr_ty, _)| {
-                    DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }
+                    DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey }
                         .types_may_unify(*rcvr_ty, impl_ty)
                 })
                 .map_or(impl_ty, |(ty, _)| ty)
@@ -1516,7 +1517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .into_iter()
             .any(|info| self.associated_value(info.def_id, item_name).is_some());
         let found_assoc = |ty: Ty<'tcx>| {
-            simplify_type(tcx, ty, TreatParams::AsInfer)
+            simplify_type(tcx, ty, TreatParams::AsCandidateKey, TreatProjections::AsCandidateKey)
                 .and_then(|simp| {
                     tcx.incoherent_impls(simp)
                         .iter()
@@ -2645,9 +2646,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // FIXME: Even though negative bounds are not implemented, we could maybe handle
                 // cases where a positive bound implies a negative impl.
                 (candidates, Vec::new())
-            } else if let Some(simp_rcvr_ty) =
-                simplify_type(self.tcx, rcvr_ty, TreatParams::AsPlaceholder)
-            {
+            } else if let Some(simp_rcvr_ty) = simplify_type(
+                self.tcx,
+                rcvr_ty,
+                TreatParams::ForLookup,
+                TreatProjections::ForLookup,
+            ) {
                 let mut potential_candidates = Vec::new();
                 let mut explicitly_negative = Vec::new();
                 for candidate in candidates {
@@ -2660,8 +2664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })
                         .any(|imp_did| {
                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
-                            let imp_simp =
-                                simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder);
+                            let imp_simp = simplify_type(
+                                self.tcx,
+                                imp.self_ty(),
+                                TreatParams::ForLookup,
+                                TreatProjections::ForLookup,
+                            );
                             imp_simp.map_or(false, |s| s == simp_rcvr_ty)
                         })
                     {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 16306bef42e..bbab8a62a2b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -26,7 +26,7 @@ use rustc_middle::middle::exported_symbols::{
 use rustc_middle::mir::interpret;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_middle::util::common::to_readable_str;
@@ -1858,7 +1858,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     let simplified_self_ty = fast_reject::simplify_type(
                         self.tcx,
                         trait_ref.self_ty(),
-                        TreatParams::AsInfer,
+                        TreatParams::AsCandidateKey,
+                        TreatProjections::AsCandidateKey,
                     );
 
                     fx_hash_map
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 5215e3db798..b34651c3ea7 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1999,6 +1999,9 @@ impl BorrowKind {
 }
 
 impl BinOp {
+    /// The checkable operators are those whose overflow checking behavior is controlled by
+    /// -Coverflow-checks option. The remaining operators have either no overflow conditions (e.g.,
+    /// BitAnd, BitOr, BitXor) or are always checked for overflow (e.g., Div, Rem).
     pub fn is_checkable(self) -> bool {
         use self::BinOp::*;
         matches!(self, Add | Sub | Mul | Shl | Shr)
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 59deade0a07..ee505742be9 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -51,15 +51,35 @@ pub enum SimplifiedType {
 /// generic parameters as if they were inference variables in that case.
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 pub enum TreatParams {
-    /// Treat parameters as placeholders in the given environment.
+    /// Treat parameters as infer vars. This is the correct mode for caching
+    /// an impl's type for lookup.
+    AsCandidateKey,
+    /// Treat parameters as placeholders in the given environment. This is the
+    /// correct mode for *lookup*, as during candidate selection.
+    ForLookup,
+}
+
+/// During fast-rejection, we have the choice of treating projection types
+/// as either simplifyable or not, depending on whether we expect the projection
+/// to be normalized/rigid.
+#[derive(PartialEq, Eq, Debug, Clone, Copy)]
+pub enum TreatProjections {
+    /// In candidates, we may be able to normalize the projection
+    /// after instantiating the candidate and equating it with a goal.
     ///
-    /// Note that this also causes us to treat projections as if they were
-    /// placeholders. This is only correct if the given projection cannot
-    /// be normalized in the current context. Even if normalization fails,
-    /// it may still succeed later if the projection contains any inference
-    /// variables.
-    AsPlaceholder,
-    AsInfer,
+    /// We must assume that the `impl<T> Trait<T> for <T as Id>::This`
+    /// can apply to all self types so we don't return a simplified type
+    /// for `<T as Id>::This`.
+    AsCandidateKey,
+    /// In the old solver we don't try to normalize projections
+    /// when looking up impls and only access them by using the
+    /// current self type. This means that if the self type is
+    /// a projection which could later be normalized, we must not
+    /// treat it as rigid.
+    ForLookup,
+    /// We can treat projections in the self type as opaque as
+    /// we separately look up impls for the normalized self type.
+    NextSolverLookup,
 }
 
 /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@@ -87,6 +107,7 @@ pub fn simplify_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
     treat_params: TreatParams,
+    treat_projections: TreatProjections,
 ) -> Option<SimplifiedType> {
     match *ty.kind() {
         ty::Bool => Some(BoolSimplifiedType),
@@ -115,19 +136,13 @@ pub fn simplify_type<'tcx>(
         ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
         ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
         ty::Param(_) => match treat_params {
-            TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
-            TreatParams::AsInfer => None,
+            TreatParams::ForLookup => Some(PlaceholderSimplifiedType),
+            TreatParams::AsCandidateKey => None,
         },
-        ty::Alias(..) => match treat_params {
-            // When treating `ty::Param` as a placeholder, projections also
-            // don't unify with anything else as long as they are fully normalized.
-            //
-            // We will have to be careful with lazy normalization here.
-            TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
-                debug!("treating `{}` as a placeholder", ty);
-                Some(PlaceholderSimplifiedType)
-            }
-            TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
+        ty::Alias(..) => match treat_projections {
+            TreatProjections::ForLookup if !ty.needs_infer() => Some(PlaceholderSimplifiedType),
+            TreatProjections::NextSolverLookup => Some(PlaceholderSimplifiedType),
+            TreatProjections::AsCandidateKey | TreatProjections::ForLookup => None,
         },
         ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
         ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
@@ -295,8 +310,8 @@ impl DeepRejectCtxt {
             // Depending on the value of `treat_obligation_params`, we either
             // treat generic parameters like placeholders or like inference variables.
             ty::Param(_) => match self.treat_obligation_params {
-                TreatParams::AsPlaceholder => false,
-                TreatParams::AsInfer => true,
+                TreatParams::ForLookup => false,
+                TreatParams::AsCandidateKey => true,
             },
 
             ty::Infer(_) => true,
@@ -333,8 +348,8 @@ impl DeepRejectCtxt {
         let k = impl_ct.kind();
         match obligation_ct.kind() {
             ty::ConstKind::Param(_) => match self.treat_obligation_params {
-                TreatParams::AsPlaceholder => false,
-                TreatParams::AsInfer => true,
+                TreatParams::ForLookup => false,
+                TreatParams::AsCandidateKey => true,
             },
 
             // As we don't necessarily eagerly evaluate constants,
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 649a58c9170..bf2b121f704 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,5 +1,5 @@
 use crate::traits::specialization_graph;
-use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{Ident, Ty, TyCtxt};
 use hir::def_id::LOCAL_CRATE;
@@ -118,16 +118,32 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Iterate over every impl that could possibly match the self type `self_ty`.
     ///
     /// `trait_def_id` MUST BE the `DefId` of a trait.
-    pub fn for_each_relevant_impl<F: FnMut(DefId)>(
+    pub fn for_each_relevant_impl(
         self,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        mut f: F,
+        f: impl FnMut(DefId),
     ) {
-        let _: Option<()> = self.find_map_relevant_impl(trait_def_id, self_ty, |did| {
-            f(did);
-            None
-        });
+        self.for_each_relevant_impl_treating_projections(
+            trait_def_id,
+            self_ty,
+            TreatProjections::ForLookup,
+            f,
+        )
+    }
+
+    pub fn for_each_relevant_impl_treating_projections(
+        self,
+        trait_def_id: DefId,
+        self_ty: Ty<'tcx>,
+        treat_projections: TreatProjections,
+        mut f: impl FnMut(DefId),
+    ) {
+        let _: Option<()> =
+            self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
+                f(did);
+                None
+            });
     }
 
     /// `trait_def_id` MUST BE the `DefId` of a trait.
@@ -137,7 +153,12 @@ impl<'tcx> TyCtxt<'tcx> {
         self_ty: Ty<'tcx>,
     ) -> impl Iterator<Item = DefId> + 'tcx {
         let impls = self.trait_impls_of(trait_def_id);
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsInfer) {
+        if let Some(simp) = fast_reject::simplify_type(
+            self,
+            self_ty,
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        ) {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 return impls.iter().copied();
             }
@@ -150,11 +171,12 @@ impl<'tcx> TyCtxt<'tcx> {
     /// the first non-none value.
     ///
     /// `trait_def_id` MUST BE the `DefId` of a trait.
-    pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(
+    pub fn find_map_relevant_impl<T>(
         self,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
-        mut f: F,
+        treat_projections: TreatProjections,
+        mut f: impl FnMut(DefId) -> Option<T>,
     ) -> Option<T> {
         // FIXME: This depends on the set of all impls for the trait. That is
         // unfortunate wrt. incremental compilation.
@@ -169,14 +191,13 @@ impl<'tcx> TyCtxt<'tcx> {
             }
         }
 
-        // Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using
-        // `TreatParams::AsInfer` while actually adding them.
-        //
         // This way, when searching for some impl for `T: Trait`, we do not look at any impls
         // whose outer level is not a parameter or projection. Especially for things like
         // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
         // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholder) {
+        if let Some(simp) =
+            fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup, treat_projections)
+        {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 for &impl_def_id in impls {
                     if let result @ Some(_) = f(impl_def_id) {
@@ -237,9 +258,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
             continue;
         }
 
-        if let Some(simplified_self_ty) =
-            fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsInfer)
-        {
+        if let Some(simplified_self_ty) = fast_reject::simplify_type(
+            tcx,
+            impl_self_ty,
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        ) {
             impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
         } else {
             impls.blanket_impls.push(impl_def_id);
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8b5469743da..b0f6127baa5 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,6 +2,7 @@
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir;
+use crate::ty::fast_reject::TreatProjections;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -363,14 +364,20 @@ impl<'tcx> TyCtxt<'tcx> {
         self.ensure().coherent_trait(drop_trait);
 
         let ty = self.type_of(adt_did).subst_identity();
-        let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
-            if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
-                if validate(self, impl_did).is_ok() {
-                    return Some((*item_id, self.constness(impl_did)));
+        let (did, constness) = self.find_map_relevant_impl(
+            drop_trait,
+            ty,
+            // FIXME: This could also be some other mode, like "unexpected"
+            TreatProjections::ForLookup,
+            |impl_did| {
+                if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
+                    if validate(self, impl_did).is_ok() {
+                        return Some((*item_id, self.constness(impl_did)));
+                    }
                 }
-            }
-            None
-        })?;
+                None
+            },
+        )?;
 
         Some(ty::Destructor { did, constness })
     }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5ef3e13eff8..c8d371dd084 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2215,7 +2215,7 @@ impl CheckAttrVisitor<'_> {
             // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
             //
             // Properly checking this means pulling in additional `rustc` crates, so we don't.
-            let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
+            let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };
 
             if sig.abi != Abi::Rust {
                 tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index 72b1b35e79b..891ea0cdebe 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::util::elaborate_predicates;
 use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult};
+use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use std::fmt::Debug;
@@ -299,9 +300,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
         let tcx = self.tcx();
-        tcx.for_each_relevant_impl(
+        tcx.for_each_relevant_impl_treating_projections(
             goal.predicate.trait_def_id(tcx),
             goal.predicate.self_ty(),
+            TreatProjections::NextSolverLookup,
             |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
                 Ok(result) => candidates
                     .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index e206658b4b9..dbb8e722c8f 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -184,7 +184,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
 
         let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
         let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
         if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs)
             .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
         {
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 0669975d638..7878539817c 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -8,7 +8,7 @@ use rustc_hir::LangItem;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::util::supertraits;
 use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
 use rustc_span::DUMMY_SP;
@@ -36,7 +36,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         let tcx = ecx.tcx();
 
         let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
         if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs)
             .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
         {
@@ -135,9 +135,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         // currently instead lint patterns which can be used to
         // exploit this unsoundness on stable, see #93367 for
         // more details.
+        //
+        // Using `TreatProjections::NextSolverLookup` is fine here because
+        // `instantiate_constituent_tys_for_auto_trait` returns nothing for
+        // projection types anyways. So it doesn't really matter what we do
+        // here, and this is faster.
         if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
             goal.predicate.def_id(),
             goal.predicate.self_ty(),
+            TreatProjections::NextSolverLookup,
             Some,
         ) {
             debug!(?def_id, ?goal, "disqualified auto-trait implementation");
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 6b688c322c7..96a4b76af55 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -75,7 +75,7 @@ pub fn overlapping_impls(
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
-    let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
+    let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };
     let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
     let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
     let may_overlap = match (impl1_ref, impl2_ref) {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 704b0d0bd1c..41ffaeeac1c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -32,6 +32,7 @@ use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
@@ -1799,12 +1800,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     })
                     .and_then(|(trait_assoc_item, id)| {
                         let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-                        self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| {
-                            self.tcx
-                                .associated_items(did)
-                                .in_definition_order()
-                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
-                        })
+                        self.tcx.find_map_relevant_impl(
+                            id,
+                            proj.projection_ty.self_ty(),
+                            TreatProjections::ForLookup,
+                            |did| {
+                                self.tcx
+                                    .associated_items(did)
+                                    .in_definition_order()
+                                    .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
+                            },
+                        )
                     })
                     .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
                         Some(
@@ -2176,7 +2182,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_ref: &ty::PolyTraitRef<'tcx>,
     ) -> bool {
         let get_trait_impl = |trait_def_id| {
-            self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some)
+            self.tcx.find_map_relevant_impl(
+                trait_def_id,
+                trait_ref.skip_binder().self_ty(),
+                TreatProjections::ForLookup,
+                Some,
+            )
         };
         let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
         let traits_with_same_path: std::collections::BTreeSet<_> = self
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e91057356a2..3182af989f0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -9,6 +9,7 @@ use hir::LangItem;
 use rustc_hir as hir;
 use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
+use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_target::spec::abi::Abi;
 
@@ -783,6 +784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let relevant_impl = self.tcx().find_map_relevant_impl(
                     self.tcx().require_lang_item(LangItem::Drop, None),
                     obligation.predicate.skip_binder().trait_ref.self_ty(),
+                    TreatProjections::ForLookup,
                     Some,
                 );
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index d7ce0078124..38cdaddc1e7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2558,7 +2558,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // We can avoid creating type variables and doing the full
         // substitution if we find that any of the input types, when
         // simplified, do not match.
-        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
         iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs)
             .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp))
     }
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 61ed9ef2ec1..cd665d9471d 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -3,7 +3,7 @@ use super::OverlapError;
 use crate::traits;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 
 pub use rustc_middle::traits::specialization_graph::*;
@@ -49,8 +49,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
     /// Insert an impl into this set of children without comparing to any existing impls.
     fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer)
-        {
+        if let Some(st) = fast_reject::simplify_type(
+            tcx,
+            trait_ref.self_ty(),
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        ) {
             debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
             self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
         } else {
@@ -65,8 +69,12 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
     fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
         let vec: &mut Vec<DefId>;
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer)
-        {
+        if let Some(st) = fast_reject::simplify_type(
+            tcx,
+            trait_ref.self_ty(),
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        ) {
             debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
             vec = self.non_blanket_impls.get_mut(&st).unwrap();
         } else {
@@ -302,7 +310,12 @@ impl<'tcx> GraphExt<'tcx> for Graph {
 
         let mut parent = trait_def_id;
         let mut last_lint = None;
-        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer);
+        let simplified = fast_reject::simplify_type(
+            tcx,
+            trait_ref.self_ty(),
+            TreatParams::AsCandidateKey,
+            TreatProjections::AsCandidateKey,
+        );
 
         // Descend the specialization tree, where `parent` is the current parent node.
         loop {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 040a59184a6..123561873a6 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -960,6 +960,7 @@ impl AtomicBool {
     /// ```ignore (extern-declaration)
     /// # fn main() {
     /// use std::sync::atomic::AtomicBool;
+    ///
     /// extern "C" {
     ///     fn my_atomic_op(arg: *mut bool);
     /// }
@@ -971,7 +972,8 @@ impl AtomicBool {
     /// # }
     /// ```
     #[inline]
-    #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
+    #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_ptr(&self) -> *mut bool {
         self.v.get().cast()
     }
@@ -1890,7 +1892,6 @@ impl<T> AtomicPtr<T> {
     /// # Examples
     ///
     /// ```ignore (extern-declaration)
-    /// #![feature(atomic_mut_ptr)]
     /// use std::sync::atomic::AtomicPtr;
     ///
     /// extern "C" {
@@ -1906,7 +1907,8 @@ impl<T> AtomicPtr<T> {
     /// }
     /// ```
     #[inline]
-    #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
+    #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_ptr(&self) -> *mut *mut T {
         self.p.get()
     }
@@ -2859,9 +2861,8 @@ macro_rules! atomic_int {
             /// # }
             /// ```
             #[inline]
-            #[unstable(feature = "atomic_mut_ptr",
-                   reason = "recently added",
-                   issue = "66893")]
+            #[stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
+            #[rustc_const_stable(feature = "atomic_as_ptr", since = "CURRENT_RUSTC_VERSION")]
             pub const fn as_ptr(&self) -> *mut $int_type {
                 self.v.get()
             }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 7837dd276d2..4e7b6080835 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -274,7 +274,6 @@
 #![feature(utf8_chunks)]
 //
 // Library features (core):
-#![feature(atomic_mut_ptr)]
 #![feature(char_internals)]
 #![feature(core_intrinsics)]
 #![feature(duration_constants)]
diff --git a/library/std/src/sys/hermit/futex.rs b/library/std/src/sys/hermit/futex.rs
index b64c174b06c..427d8ff6f2e 100644
--- a/library/std/src/sys/hermit/futex.rs
+++ b/library/std/src/sys/hermit/futex.rs
@@ -16,7 +16,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 
     let r = unsafe {
         abi::futex_wait(
-            futex.as_mut_ptr(),
+            futex.as_ptr(),
             expected,
             timespec.as_ref().map_or(null(), |t| t as *const abi::timespec),
             abi::FUTEX_RELATIVE_TIMEOUT,
@@ -28,12 +28,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 
 #[inline]
 pub fn futex_wake(futex: &AtomicU32) -> bool {
-    unsafe { abi::futex_wake(futex.as_mut_ptr(), 1) > 0 }
+    unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 }
 }
 
 #[inline]
 pub fn futex_wake_all(futex: &AtomicU32) {
     unsafe {
-        abi::futex_wake(futex.as_mut_ptr(), i32::MAX);
+        abi::futex_wake(futex.as_ptr(), i32::MAX);
     }
 }
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index d34a4cfedea..743e93a2fd4 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -15,7 +15,6 @@
 
 #![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)]
 
-use crate::intrinsics;
 use crate::os::raw::c_char;
 
 pub mod alloc;
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 648eb553c78..54d0d8a8ec2 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -47,6 +47,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage
   0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed
   [#77120](https://github.com/rust-lang/rust/pull/77120).
+- File locking is now used to avoid collisions between multiple running instances of `x.py` (e.g. when using `rust-analyzer` and `x.py` at the same time). Note that Solaris and possibly other non Unix and non Windows systems don't support it [#108607](https://github.com/rust-lang/rust/pull/108607). This might possibly lead to build data corruption.
 
 
 ## [Version 1] - 2020-09-11
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 663987f113c..afe3fc1741b 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -32,7 +32,6 @@ test = false
 [dependencies]
 build_helper = { path = "../tools/build_helper" }
 cmake = "0.1.38"
-fd-lock = "3.0.8"
 filetime = "0.2"
 getopts = "0.2.19"
 cc = "1.0.69"
@@ -56,6 +55,10 @@ walkdir = "2"
 # Dependencies needed by the build-metrics feature
 sysinfo = { version = "0.26.0", optional = true }
 
+# Solaris doesn't support flock() and thus fd-lock is not option now
+[target.'cfg(not(target_os = "solaris"))'.dependencies]
+fd-lock = "3.0.8"
+
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
 features = [
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index b345bf9fb83..912d875e445 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -7,15 +7,18 @@
 
 use std::env;
 
-use bootstrap::{t, Build, Config, Subcommand, VERSION};
+#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+use bootstrap::t;
+use bootstrap::{Build, Config, Subcommand, VERSION};
 
 fn main() {
     let args = env::args().skip(1).collect::<Vec<_>>();
     let config = Config::parse(&args);
 
-    let mut build_lock;
-    let _build_lock_guard;
-    if cfg!(any(unix, windows)) {
+    #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+    {
+        let mut build_lock;
+        let _build_lock_guard;
         let path = config.out.join("lock");
         build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
         _build_lock_guard = match build_lock.try_write() {
@@ -30,9 +33,9 @@ fn main() {
                 t!(build_lock.write())
             }
         };
-    } else {
-        println!("warning: file locking not supported for target, not locking build directory");
     }
+    #[cfg(any(not(any(unix, windows)), target_os = "solaris"))]
+    println!("warning: file locking not supported for target, not locking build directory");
 
     // check_version warnings are not printed during setup
     let changelog_suggestion =
@@ -125,7 +128,7 @@ fn get_lock_owner(f: &std::path::Path) -> Option<u64> {
     })
 }
 
-#[cfg(not(target_os = "linux"))]
+#[cfg(not(any(target_os = "linux", target_os = "solaris")))]
 fn get_lock_owner(_: &std::path::Path) -> Option<u64> {
     // FIXME: Implement on other OS's
     None
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 5a105007f21..16dc8c63abc 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -1,5 +1,5 @@
 use super::{Config, TomlConfig};
-use std::path::Path;
+use std::{env, path::Path};
 
 fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
     |&_| toml::from_str(config).unwrap()
@@ -33,4 +33,35 @@ fn download_ci_llvm() {
     ));
 }
 
-// FIXME: add test for detecting `src` and `out`
+#[test]
+fn detect_src_and_out() {
+    let cfg = parse("");
+
+    // This will bring absolute form of `src/bootstrap` path
+    let current_dir = std::env::current_dir().unwrap();
+
+    // get `src` by moving into project root path
+    let expected_src = current_dir.ancestors().nth(2).unwrap();
+
+    assert_eq!(&cfg.src, expected_src);
+
+    // This should bring output path of bootstrap in absolute form
+    let cargo_target_dir = env::var_os("CARGO_TARGET_DIR")
+        .expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap");
+
+    // Move to `build` from `build/bootstrap`
+    let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
+    assert_eq!(&cfg.out, expected_out);
+
+    let args: Vec<String> = env::args().collect();
+
+    // Another test for `out` as a sanity check
+    //
+    // This will bring something similar to:
+    //     `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
+    // `{config_toml_place}` can be anywhere, not just in the rust project directory.
+    let dep = Path::new(args.first().unwrap());
+    let expected_out = dep.ancestors().nth(4).unwrap();
+
+    assert_eq!(&cfg.out, expected_out);
+}
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 79b53665a7c61d171fb8c5ad0b73b371f9ee6ba
+Subproject 1f3e4cd4fd88b5b5d45feb86a11b6d2f93e5a97
diff --git a/src/doc/reference b/src/doc/reference
-Subproject a9afb04b47a84a6753e4dc657348c324c876102
+Subproject 24c87f6663aed55b05d2cc286878f28f2191882
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject b06dab84083390e0ee1e998f466545a8a1a76a9
+Subproject b1b6d693cd1461e53de4132c1b183ace31cd36e
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index bcb69d1a4ca..358f6ad566c 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::Mutability;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::{fast_reject::TreatProjections, Ty, TyCtxt};
 use rustc_middle::{bug, ty};
 use rustc_resolve::rustdoc::MalformedGenerics;
 use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path};
@@ -735,7 +735,7 @@ fn trait_impls_for<'a>(
         trace!("considering explicit impl for trait {:?}", trait_);
 
         // Look at each trait implementation to see if it's an impl for `did`
-        tcx.find_map_relevant_impl(trait_, ty, |impl_| {
+        tcx.find_map_relevant_impl(trait_, ty, TreatProjections::ForLookup, |impl_| {
             let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
             // Check if these are the same type.
             let impl_type = trait_ref.skip_binder().self_ty();
diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs
index 04314dc291a..db2aa20bde7 100644
--- a/tests/codegen/simd-wide-sum.rs
+++ b/tests/codegen/simd-wide-sum.rs
@@ -1,4 +1,4 @@
-// compile-flags: -C opt-level=3 --edition=2021
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
 // only-x86_64
 // ignore-debug: the debug assertions get in the way
 
diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs
index ad1b6e96be6..0c400d7bf97 100644
--- a/tests/ui/target-feature/invalid-attribute.rs
+++ b/tests/ui/target-feature/invalid-attribute.rs
@@ -14,6 +14,21 @@
 
 #![warn(unused_attributes)]
 
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+extern crate alloc;
+//~^ NOTE not a function
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+use alloc::alloc::alloc;
+//~^ NOTE not a function
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+extern "Rust" {}
+//~^ NOTE not a function
+
 #[target_feature = "+sse2"]
 //~^ ERROR malformed `target_feature` attribute
 #[target_feature(enable = "foo")]
@@ -61,6 +76,11 @@ union Qux {
 
 #[target_feature(enable = "sse2")]
 //~^ ERROR attribute should be applied to a function
+type Uwu = ();
+//~^ NOTE not a function
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
 trait Baz {}
 //~^ NOTE not a function
 
@@ -69,6 +89,21 @@ trait Baz {}
 #[target_feature(enable = "sse2")]
 unsafe fn test() {}
 
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+static A: () = ();
+//~^ NOTE not a function
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+impl Quux for u8 {}
+//~^ NOTE not a function
+
+#[target_feature(enable = "sse2")]
+//~^ ERROR attribute should be applied to a function
+impl Foo {}
+//~^ NOTE not a function
+
 trait Quux {
     fn foo();
 }
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index a2adfc67f08..6d37d0917bc 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -1,11 +1,38 @@
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:17:1
+  --> $DIR/invalid-attribute.rs:32:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:34:1
+  --> $DIR/invalid-attribute.rs:17:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | extern crate alloc;
+   | ------------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:22:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | use alloc::alloc::alloc;
+   | ------------------------ not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:27:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | extern "Rust" {}
+   | ---------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:49:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -14,7 +41,7 @@ LL | mod another {}
    | -------------- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:39:1
+  --> $DIR/invalid-attribute.rs:54:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +50,7 @@ LL | const FOO: usize = 7;
    | --------------------- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:44:1
+  --> $DIR/invalid-attribute.rs:59:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +59,7 @@ LL | struct Foo;
    | ----------- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:49:1
+  --> $DIR/invalid-attribute.rs:64:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,7 +68,7 @@ LL | enum Bar {}
    | ----------- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:54:1
+  --> $DIR/invalid-attribute.rs:69:1
    |
 LL |   #[target_feature(enable = "sse2")]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,7 +81,16 @@ LL | | }
    | |_- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:62:1
+  --> $DIR/invalid-attribute.rs:77:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | type Uwu = ();
+   | -------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:82:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +99,34 @@ LL | trait Baz {}
    | ------------ not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:85:5
+  --> $DIR/invalid-attribute.rs:92:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | static A: () = ();
+   | ------------------ not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:97:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | impl Quux for u8 {}
+   | ------------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:102:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | impl Foo {}
+   | ----------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/invalid-attribute.rs:120:5
    |
 LL |       #[target_feature(enable = "sse2")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,7 +138,7 @@ LL | |     }
    | |_____- not a function definition
 
 error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:93:5
+  --> $DIR/invalid-attribute.rs:128:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,25 +147,25 @@ LL |     || {};
    |     ----- not a function definition
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/invalid-attribute.rs:19:18
+  --> $DIR/invalid-attribute.rs:34:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^ `foo` is not valid for this target
 
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:22:18
+  --> $DIR/invalid-attribute.rs:37:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^ help: must be of the form: `enable = ".."`
 
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:24:18
+  --> $DIR/invalid-attribute.rs:39:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
 
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
-  --> $DIR/invalid-attribute.rs:28:1
+  --> $DIR/invalid-attribute.rs:43:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -114,13 +177,13 @@ LL | fn bar() {}
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
 
 error: cannot use `#[inline(always)]` with `#[target_feature]`
-  --> $DIR/invalid-attribute.rs:67:1
+  --> $DIR/invalid-attribute.rs:87:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
-  --> $DIR/invalid-attribute.rs:77:5
+  --> $DIR/invalid-attribute.rs:112:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,6 +194,6 @@ LL |     fn foo() {}
    = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
 
-error: aborting due to 15 previous errors
+error: aborting due to 22 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs
new file mode 100644
index 00000000000..92bad959095
--- /dev/null
+++ b/tests/ui/traits/new-solver/nested-obligations-with-bound-vars-gat.rs
@@ -0,0 +1,43 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+// Issue 96230
+
+use std::fmt::Debug;
+
+trait Classic {
+    type Assoc;
+}
+
+trait Gat {
+    type Assoc<'a>;
+}
+
+struct Foo;
+
+impl Classic for Foo {
+    type Assoc = ();
+}
+
+impl Gat for Foo {
+    type Assoc<'i> = ();
+}
+
+fn classic_debug<T: Classic>(_: T)
+where
+    T::Assoc: Debug,
+{
+}
+
+fn gat_debug<T: Gat>(_: T)
+where
+    for<'a> T::Assoc<'a>: Debug,
+{
+}
+
+fn main() {
+    classic_debug::<Foo>(Foo); // fine
+    classic_debug(Foo); // fine
+
+    gat_debug::<Foo>(Foo); // fine
+    gat_debug(Foo); // boom
+}
diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs
new file mode 100644
index 00000000000..1dca86d3630
--- /dev/null
+++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Ztrait-solver=next
+
+// In the new solver, we are trying to select `<?0 as Iterator>::Item: Debug`,
+// which, naively can be unified with every impl of `Debug` if we're not careful.
+// This test makes sure that we treat projections with inference var substs as
+// placeholders during fast reject.
+
+fn iter<T: Iterator>() -> <T as Iterator>::Item {
+    todo!()
+}
+
+fn main() {
+    println!("{:?}", iter::<_>());
+    //~^ ERROR type annotations needed
+}
diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr
new file mode 100644
index 00000000000..47004821ad7
--- /dev/null
+++ b/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/runaway-impl-candidate-selection.rs:13:22
+   |
+LL |     println!("{:?}", iter::<_>());
+   |                      ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.