about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-21 13:32:14 +0000
committerbors <bors@rust-lang.org>2020-08-21 13:32:14 +0000
commitcfbc6d4cf1acbac5c025acf8ed68929caa551df3 (patch)
tree8afc37471942c7ed5ac8fe051de4460a68fca8ef
parent32c481e156c6431d2947d865bd2abc2315a931fc (diff)
parent68d6e56fea002401c7b20769f33ae806d8e59dc1 (diff)
downloadrust-cfbc6d4cf1acbac5c025acf8ed68929caa551df3.tar.gz
rust-cfbc6d4cf1acbac5c025acf8ed68929caa551df3.zip
Auto merge of #75722 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
[beta] backports

* Fix regionck failure when converting Index to IndexMut #74960
* Update RELEASES.md for 1.46.0 #74744
* allow escaping bound vars when normalizing `ty::Opaque` #75443

r? @ghost
-rw-r--r--RELEASES.md137
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh2
-rw-r--r--src/librustc_trait_selection/traits/auto_trait.rs12
-rw-r--r--src/librustc_trait_selection/traits/fulfill.rs16
-rw-r--r--src/librustc_trait_selection/traits/mod.rs4
-rw-r--r--src/librustc_trait_selection/traits/project.rs81
-rw-r--r--src/librustc_trait_selection/traits/query/normalize.rs6
-rw-r--r--src/librustc_trait_selection/traits/select/mod.rs10
-rw-r--r--src/librustc_typeck/check/place_op.rs37
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-1.rs8
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-1.stderr21
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-2.rs10
-rw-r--r--src/test/ui/associated-types/defaults-cyclic-fail-2.stderr22
-rw-r--r--src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs20
-rw-r--r--src/test/ui/associated-types/normalize-cycle-in-eval.rs43
-rw-r--r--src/test/ui/auto-traits/issue-23080-2.rs2
-rw-r--r--src/test/ui/auto-traits/issue-23080-2.stderr12
-rw-r--r--src/test/ui/issues/issue-21946.rs4
-rw-r--r--src/test/ui/issues/issue-21946.stderr4
-rw-r--r--src/test/ui/issues/issue-23122-1.stderr4
-rw-r--r--src/test/ui/mir/issue-75419-validation-impl-trait.rs13
-rw-r--r--src/test/ui/typeck/issue-74933.rs38
-rwxr-xr-xsrc/tools/publish_toolstate.py3
23 files changed, 393 insertions, 116 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 977796c6613..b3d8c2f65f6 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,128 @@
+Version 1.46.0 (2020-08-27)
+==========================
+
+Language
+--------
+- [`if`, `match`, and `loop` expressions can now be used in const functions.][72437]
+- [Additionally you are now also able to coerce and cast to slices (`&[T]`) in
+  const functions.][73862]
+- [The `#[track_caller]` attribute can now be added to functions to use the
+  function's caller's location information for panic messages.][72445]
+- [Recursively indexing into tuples no longer needs parentheses.][71322] E.g.
+  `x.0.0` over `(x.0).0`.
+- [`mem::transmute` can now be used in static and constants.][72920] **Note**
+  You currently can't use `mem::transmute` in constant functions.
+
+Compiler
+--------
+- [You can now use the `cdylib` target on Apple iOS and tvOS platforms.][73516]
+- [Enabled static "Position Independent Executables" by default
+  for `x86_64-unknown-linux-musl`.][70740]
+
+Libraries
+---------
+- [`mem::forget` is now a `const fn`.][73887]
+- [`String` now implements `From<char>`.][73466]
+- [The `leading_ones`, and `trailing_ones` methods have been stabilised for all
+  integer types.][73032]
+- [`vec::IntoIter<T>` now implements `AsRef<[T]>`.][72583]
+- [All non-zero integer types (`NonZeroU8`) now implement `TryFrom` for their
+  zero-able equivalent (e.g. `TryFrom<u8>`).][72717]
+- [`&[T]` and `&mut [T]` now implement `PartialEq<Vec<T>>`.][71660]
+- [`(String, u16)` now implements `ToSocketAddrs`.][73007]
+- [`vec::Drain<'_, T>` now implements `AsRef<[T]>`.][72584]
+
+Stabilized APIs
+---------------
+- [`Option::zip`]
+- [`vec::Drain::as_slice`]
+
+Cargo
+-----
+Added a number of new environment variables that are now available when
+compiling your crate.
+
+- [`CARGO_BIN_NAME` and `CARGO_CRATE_NAME`][cargo/8270] Providing the name of
+  the specific binary being compiled and the name of the crate.
+- [`CARGO_PKG_LICENSE`][cargo/8325] The license from the manifest of the package.
+- [`CARGO_PKG_LICENSE_FILE`][cargo/8387] The path to the license file.
+
+Compatibility Notes
+-------------------
+- [The target configuration option `abi_blacklist` has been renamed
+  to `unsupported_abis`.][74150] The old name will still continue to work.
+- [Rustc will now warn if you have a C-like enum that implements `Drop`.][72331]
+  This was previously accepted but will become a hard error in a future release.
+- [Rustc will fail to compile if you have a struct with
+  `#[repr(i128)]` or `#[repr(u128)]`.][74109] This representation is currently only
+  allowed on `enum`s.
+- [Tokens passed to `macro_rules!` are now always captured.][73293] This helps
+  ensure that spans have the correct information, and may cause breakage if you
+  were relying on receiving spans with dummy information.
+- [The InnoSetup installer for Windows is no longer available.][72569] This was
+  a legacy installer that was replaced by a MSI installer a few years ago but
+  was still being built.
+- [`{f32, f64}::asinh` now returns the correct values for negative numbers.][72486]
+- [Rustc will no longer accept overlapping trait implementations that only
+  differ in how the lifetime was bound.][72493]
+- [Rustc now correctly relates the lifetime of an existential associated
+  type.][71896] This fixes some edge cases where `rustc` would erroneously allow
+  you to pass a shorter lifetime than expected.
+
+[74109]: https://github.com/rust-lang/rust/pull/74109/
+[74150]: https://github.com/rust-lang/rust/pull/74150/
+[73862]: https://github.com/rust-lang/rust/pull/73862/
+[73887]: https://github.com/rust-lang/rust/pull/73887/
+[73466]: https://github.com/rust-lang/rust/pull/73466/
+[73516]: https://github.com/rust-lang/rust/pull/73516/
+[73293]: https://github.com/rust-lang/rust/pull/73293/
+[73007]: https://github.com/rust-lang/rust/pull/73007/
+[73032]: https://github.com/rust-lang/rust/pull/73032/
+[72920]: https://github.com/rust-lang/rust/pull/72920/
+[72569]: https://github.com/rust-lang/rust/pull/72569/
+[72583]: https://github.com/rust-lang/rust/pull/72583/
+[72584]: https://github.com/rust-lang/rust/pull/72584/
+[72717]: https://github.com/rust-lang/rust/pull/72717/
+[72437]: https://github.com/rust-lang/rust/pull/72437/
+[72445]: https://github.com/rust-lang/rust/pull/72445/
+[72486]: https://github.com/rust-lang/rust/pull/72486/
+[72493]: https://github.com/rust-lang/rust/pull/72493/
+[72331]: https://github.com/rust-lang/rust/pull/72331/
+[71896]: https://github.com/rust-lang/rust/pull/71896/
+[71660]: https://github.com/rust-lang/rust/pull/71660/
+[71322]: https://github.com/rust-lang/rust/pull/71322/
+[70740]: https://github.com/rust-lang/rust/pull/70740/
+[cargo/8270]: https://github.com/rust-lang/cargo/pull/8270/
+[cargo/8325]: https://github.com/rust-lang/cargo/pull/8325/
+[cargo/8387]: https://github.com/rust-lang/cargo/pull/8387/
+[`Option::zip`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.zip
+[`vec::Drain::as_slice`]: https://doc.rust-lang.org/stable/std/vec/struct.Drain.html#method.as_slice
+
+
+Version 1.45.2 (2020-08-03)
+==========================
+
+* [Fix bindings in tuple struct patterns][74954]
+* [Fix track_caller integration with trait objects][74784]
+
+[74954]: https://github.com/rust-lang/rust/issues/74954
+[74784]: https://github.com/rust-lang/rust/issues/74784
+
+
+Version 1.45.1 (2020-07-30)
+==========================
+
+* [Fix const propagation with references.][73613]
+* [rustfmt accepts rustfmt_skip in cfg_attr again.][73078]
+* [Avoid spurious implicit region bound.][74509]
+* [Install clippy on x.py install][74457]
+
+[73613]: https://github.com/rust-lang/rust/pull/73613
+[73078]: https://github.com/rust-lang/rust/issues/73078
+[74509]: https://github.com/rust-lang/rust/pull/74509
+[74457]: https://github.com/rust-lang/rust/pull/74457
+
+
 Version 1.45.0 (2020-07-16)
 ==========================
 
@@ -47,7 +172,7 @@ Libraries
   // Prints "abcdefghijklmnopqrstuvwxyz"
   ```
 - [`OsString` now implements `FromStr`.][71662]
-- [The `saturating_neg` method as been added to all signed integer primitive
+- [The `saturating_neg` method has been added to all signed integer primitive
   types, and the `saturating_abs` method has been added for all integer
   primitive types.][71886]
 - [`Arc<T>`, `Rc<T>` now implement  `From<Cow<'_, T>>`, and `Box` now
@@ -82,6 +207,9 @@ Stabilized APIs
 Cargo
 -----
 
+- [Cargo uses the `embed-bitcode` flag to optimize disk usage and build
+  time.][cargo/8066]
+
 Misc
 ----
 - [Rustdoc now supports strikethrough text in Markdown.][71928] E.g.
@@ -97,12 +225,18 @@ Compatibility Notes
 - [Rustdoc's CLI's extra error exit codes have been removed.][71900] These were
   previously undocumented and not intended for public use. Rustdoc still provides
   a non-zero exit code on errors.
+- [Rustc's `lto` flag is incompatible with the new `embed-bitcode=no`.][71848]
+  This may cause issues if LTO is enabled through `RUSTFLAGS` or `cargo rustc`
+  flags while cargo is adding `embed-bitcode` itself. The recommended way to
+  control LTO is with Cargo profiles, either in `Cargo.toml` or `.cargo/config`,
+  or by setting `CARGO_PROFILE_<name>_LTO` in the environment.
 
 Internals Only
 --------------
 - [Make clippy a git subtree instead of a git submodule][70655]
 - [Unify the undo log of all snapshot types][69464]
 
+[71848]: https://github.com/rust-lang/rust/issues/71848/
 [73420]: https://github.com/rust-lang/rust/issues/73420/
 [72324]: https://github.com/rust-lang/rust/pull/72324/
 [71843]: https://github.com/rust-lang/rust/pull/71843/
@@ -129,6 +263,7 @@ Internals Only
 [69813]: https://github.com/rust-lang/rust/pull/69813/
 [69464]: https://github.com/rust-lang/rust/pull/69464/
 [68717]: https://github.com/rust-lang/rust/pull/68717/
+[cargo/8066]: https://github.com/rust-lang/cargo/pull/8066
 [`Arc::as_ptr`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.as_ptr
 [`BTreeMap::remove_entry`]: https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.remove_entry
 [`Rc::as_ptr`]: https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh
index 78bf4527fef..1c0ef6c2b30 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh
@@ -7,7 +7,7 @@ target="x86_64-fortanix-unknown-sgx"
 
 install_prereq() {
     curl https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add -
-    add-apt-repository -y 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main'
+    add-apt-repository -y 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main'
     apt-get update
     apt-get install -y --no-install-recommends \
             build-essential \
diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs
index 8c8550d377a..45dbaead08c 100644
--- a/src/librustc_trait_selection/traits/auto_trait.rs
+++ b/src/librustc_trait_selection/traits/auto_trait.rs
@@ -729,7 +729,7 @@ impl AutoTraitFinder<'tcx> {
                     // and turn them into an explicit negative impl for our type.
                     debug!("Projecting and unifying projection predicate {:?}", predicate);
 
-                    match poly_project_and_unify_type(select, &obligation.with(p)) {
+                    match project::poly_project_and_unify_type(select, &obligation.with(p)) {
                         Err(e) => {
                             debug!(
                                 "evaluate_nested_obligations: Unable to unify predicate \
@@ -738,7 +738,11 @@ impl AutoTraitFinder<'tcx> {
                             );
                             return false;
                         }
-                        Ok(Some(v)) => {
+                        Ok(Err(project::InProgress)) => {
+                            debug!("evaluate_nested_obligations: recursive projection predicate");
+                            return false;
+                        }
+                        Ok(Ok(Some(v))) => {
                             // We only care about sub-obligations
                             // when we started out trying to unify
                             // some inference variables. See the comment above
@@ -757,8 +761,8 @@ impl AutoTraitFinder<'tcx> {
                                 }
                             }
                         }
-                        Ok(None) => {
-                            // It's ok not to make progress when hvave no inference variables -
+                        Ok(Ok(None)) => {
+                            // It's ok not to make progress when have no inference variables -
                             // in that case, we were only performing unifcation to check if an
                             // error occurred (which would indicate that it's impossible for our
                             // type to implement the auto trait).
diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
index 800aef7284f..87960076a89 100644
--- a/src/librustc_trait_selection/traits/fulfill.rs
+++ b/src/librustc_trait_selection/traits/fulfill.rs
@@ -426,14 +426,20 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
 
             ty::PredicateKind::Projection(ref data) => {
                 let project_obligation = obligation.with(*data);
+                let tcx = self.selcx.tcx();
                 match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
-                    Ok(None) => {
-                        let tcx = self.selcx.tcx();
-                        pending_obligation.stalled_on =
-                            trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref(tcx));
+                    Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
+                    Ok(Ok(None)) => {
+                        pending_obligation.stalled_on = trait_ref_infer_vars(
+                            self.selcx,
+                            project_obligation.predicate.to_poly_trait_ref(tcx),
+                        );
                         ProcessResult::Unchanged
                     }
-                    Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)),
+                    // Let the caller handle the recursion
+                    Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![
+                        pending_obligation.obligation.clone(),
+                    ])),
                     Err(e) => ProcessResult::Error(CodeProjectionError(e)),
                 }
             }
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
index e8006129e3e..0585c1bd416 100644
--- a/src/librustc_trait_selection/traits/mod.rs
+++ b/src/librustc_trait_selection/traits/mod.rs
@@ -51,9 +51,7 @@ pub use self::object_safety::is_vtable_safe_method;
 pub use self::object_safety::MethodViolationCode;
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
-pub use self::project::{
-    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
-};
+pub use self::project::{normalize, normalize_projection_type, normalize_to};
 pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index bd86109e5a4..f02702cae0f 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -40,6 +40,8 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
 
 pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
 
+pub(super) struct InProgress;
+
 /// When attempting to resolve `<T as TraitRef>::Name` ...
 #[derive(Debug)]
 pub enum ProjectionTyError<'tcx> {
@@ -142,10 +144,26 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
 ///
 /// If successful, this may result in additional obligations. Also returns
 /// the projection cache key used to track these additional obligations.
-pub fn poly_project_and_unify_type<'cx, 'tcx>(
+///
+/// ## Returns
+///
+/// - `Err(_)`: the projection can be normalized, but is not equal to the
+///   expected type.
+/// - `Ok(Err(InProgress))`: this is called recursively while normalizing
+///   the same projection.
+/// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity
+///   (resolving some inference variables in the projection may fix this).
+/// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to
+///    the given obligations. If the projection cannot be normalized because
+///    the required trait bound doesn't hold this returned with `obligations`
+///    being a predicate that cannot be proven.
+pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &PolyProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+) -> Result<
+    Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
+    MismatchedProjectionTypes<'tcx>,
+> {
     debug!("poly_project_and_unify_type(obligation={:?})", obligation);
 
     let infcx = selcx.infcx();
@@ -164,10 +182,15 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>(
 ///     <T as Trait>::U == V
 ///
 /// If successful, this may result in additional obligations.
+///
+/// See [poly_project_and_unify_type] for an explanation of the return value.
 fn project_and_unify_type<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+) -> Result<
+    Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
+    MismatchedProjectionTypes<'tcx>,
+> {
     debug!("project_and_unify_type(obligation={:?})", obligation);
 
     let mut obligations = vec![];
@@ -179,8 +202,9 @@ fn project_and_unify_type<'cx, 'tcx>(
         obligation.recursion_depth,
         &mut obligations,
     ) {
-        Some(n) => n,
-        None => return Ok(None),
+        Ok(Some(n)) => n,
+        Ok(None) => return Ok(Ok(None)),
+        Err(InProgress) => return Ok(Err(InProgress)),
     };
 
     debug!(
@@ -195,7 +219,7 @@ fn project_and_unify_type<'cx, 'tcx>(
     {
         Ok(InferOk { obligations: inferred_obligations, value: () }) => {
             obligations.extend(inferred_obligations);
-            Ok(Some(obligations))
+            Ok(Ok(Some(obligations)))
         }
         Err(err) => {
             debug!("project_and_unify_type: equating types encountered error {:?}", err);
@@ -323,8 +347,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty,
@@ -352,9 +375,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
             }
 
             ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-
-                // (*) This is kind of hacky -- we need to be able to
+                // This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
                 // otherwise we wind up a need to normalize when doing
                 // trait matching (since you can have a trait
@@ -421,6 +442,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
         depth,
         obligations,
     )
+    .ok()
+    .flatten()
     .unwrap_or_else(move || {
         // if we bottom out in ambiguity, create a type variable
         // and a deferred predicate to resolve this when more type
@@ -457,7 +480,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Option<Ty<'tcx>> {
+) -> Result<Option<Ty<'tcx>>, InProgress> {
     let infcx = selcx.infcx();
 
     let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
@@ -489,7 +512,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                 "opt_normalize_projection_type: \
                  found cache entry: ambiguous"
             );
-            return None;
+            return Ok(None);
         }
         Err(ProjectionCacheEntry::InProgress) => {
             // If while normalized A::B, we are asked to normalize
@@ -504,24 +527,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             // to normalize `A::B`, we will want to check the
             // where-clauses in scope. So we will try to unify `A::B`
             // with `A::B`, which can trigger a recursive
-            // normalization. In that case, I think we will want this code:
-            //
-            // ```
-            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
-            //                                    projection_ty.substs;
-            // return Some(NormalizedTy { value: v, obligations: vec![] });
-            // ```
+            // normalization.
 
             debug!(
                 "opt_normalize_projection_type: \
                  found cache entry: in-progress"
             );
 
-            // But for now, let's classify this as an overflow:
-            let recursion_limit = selcx.tcx().sess.recursion_limit();
-            let obligation =
-                Obligation::with_depth(cause, recursion_limit.0, param_env, projection_ty);
-            selcx.infcx().report_overflow_error(&obligation, false);
+            return Err(InProgress);
         }
         Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
             // This is the hottest path in this function.
@@ -557,7 +570,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                 cause,
                 depth,
             ));
-            return Some(ty.value);
+            return Ok(Some(ty.value));
         }
         Err(ProjectionCacheEntry::Error) => {
             debug!(
@@ -566,7 +579,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             );
             let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
             obligations.extend(result.obligations);
-            return Some(result.value);
+            return Ok(Some(result.value));
         }
     }
 
@@ -613,7 +626,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             let cache_value = prune_cache_value_obligations(infcx, &result);
             infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, cache_value);
             obligations.extend(result.obligations);
-            Some(result.value)
+            Ok(Some(result.value))
         }
         Ok(ProjectedTy::NoProgress(projected_ty)) => {
             debug!(
@@ -624,7 +637,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             let result = Normalized { value: projected_ty, obligations: vec![] };
             infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
             // No need to extend `obligations`.
-            Some(result.value)
+            Ok(Some(result.value))
         }
         Err(ProjectionTyError::TooManyCandidates) => {
             debug!(
@@ -632,7 +645,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                  too many candidates"
             );
             infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
-            None
+            Ok(None)
         }
         Err(ProjectionTyError::TraitSelectionError(_)) => {
             debug!("opt_normalize_projection_type: ERROR");
@@ -644,7 +657,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             infcx.inner.borrow_mut().projection_cache().error(cache_key);
             let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
             obligations.extend(result.obligations);
-            Some(result.value)
+            Ok(Some(result.value))
         }
     }
 }
@@ -1115,11 +1128,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
             }
             super::ImplSourceAutoImpl(..) | super::ImplSourceBuiltin(..) => {
                 // These traits have no associated types.
-                span_bug!(
+                selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
-                    "Cannot project an associated type from `{:?}`",
-                    impl_source
+                    &format!("Cannot project an associated type from `{:?}`", impl_source),
                 );
+                return Err(());
             }
         };
 
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 59fa4c1598d..93652329305 100644
--- a/src/librustc_trait_selection/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -101,8 +101,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty,
@@ -140,8 +139,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
             }
 
             ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-                // (*) This is kind of hacky -- we need to be able to
+                // This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
                 // otherwise we wind up a need to normalize when doing
                 // trait matching (since you can have a trait
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index ba5e60012da..5c759e82c24 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -458,7 +458,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             &ty::PredicateKind::Projection(data) => {
                 let project_obligation = obligation.with(data);
                 match project::poly_project_and_unify_type(self, &project_obligation) {
-                    Ok(Some(mut subobligations)) => {
+                    Ok(Ok(Some(mut subobligations))) => {
                         self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
                         let result = self.evaluate_predicates_recursively(
                             previous_stack,
@@ -471,7 +471,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         }
                         result
                     }
-                    Ok(None) => Ok(EvaluatedToAmbig),
+                    Ok(Ok(None)) => Ok(EvaluatedToAmbig),
+                    // EvaluatedToRecur might also be acceptable here, but use
+                    // Unknown for now because it means that we won't dismiss a
+                    // selection candidate solely because it has a projection
+                    // cycle. This is closest to the previous behavior of
+                    // immediately erroring.
+                    Ok(Err(project::InProgress)) => Ok(EvaluatedToUnknown),
                     Err(_) => Ok(EvaluatedToErr),
                 }
             }
diff --git a/src/librustc_typeck/check/place_op.rs b/src/librustc_typeck/check/place_op.rs
index b7c8f310a14..cf2a47b59a4 100644
--- a/src/librustc_typeck/check/place_op.rs
+++ b/src/librustc_typeck/check/place_op.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::autoderef::Autoderef;
+use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@@ -245,19 +246,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             match expr.kind {
-                hir::ExprKind::Index(ref base_expr, ref index_expr) => {
-                    // We need to get the final type in case dereferences were needed for the trait
-                    // to apply (#72002).
-                    let index_expr_ty = self.tables.borrow().expr_ty_adjusted(index_expr);
-                    self.convert_place_op_to_mutable(
-                        PlaceOp::Index,
-                        expr,
-                        base_expr,
-                        &[index_expr_ty],
-                    );
+                hir::ExprKind::Index(ref base_expr, ..) => {
+                    self.convert_place_op_to_mutable(PlaceOp::Index, expr, base_expr);
                 }
                 hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base_expr) => {
-                    self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr, &[]);
+                    self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr);
                 }
                 _ => {}
             }
@@ -269,9 +262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         op: PlaceOp,
         expr: &hir::Expr<'_>,
         base_expr: &hir::Expr<'_>,
-        arg_tys: &[Ty<'tcx>],
     ) {
-        debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys);
+        debug!("convert_place_op_to_mutable({:?}, {:?}, {:?})", op, expr, base_expr);
         if !self.tables.borrow().is_method_call(expr) {
             debug!("convert_place_op_to_mutable - builtin, nothing to do");
             return;
@@ -286,6 +278,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .expect("place op takes something that is not a ref")
             .ty;
 
+        let arg_ty = match op {
+            PlaceOp::Deref => None,
+            PlaceOp::Index => {
+                // We would need to recover the `T` used when we resolve `<_ as Index<T>>::index`
+                // in try_index_step. This is the subst at index 1.
+                //
+                // Note: we should *not* use `expr_ty` of index_expr here because autoderef
+                // during coercions can cause type of index_expr to differ from `T` (#72002).
+                // We also could not use `expr_ty_adjusted` of index_expr because reborrowing
+                // during coercions can also cause type of index_expr to differ from `T`,
+                // which can potentially cause regionck failure (#74933).
+                Some(self.tables.borrow().node_substs(expr.hir_id).type_at(1))
+            }
+        };
+        let arg_tys = match arg_ty {
+            None => &[],
+            Some(ref ty) => slice::from_ref(ty),
+        };
+
         let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
         let method = match method {
             Some(ok) => self.register_infer_ok_obligations(ok),
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs
index 71ac914ef57..fa75f6bc152 100644
--- a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs
@@ -26,16 +26,16 @@ impl Tr for u32 {
 
 // ...but only if this actually breaks the cycle
 impl Tr for bool {
-//~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
     type A = Box<Self::B>;
-    //~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
 }
 // (the error is shown twice for some reason)
 
 impl Tr for usize {
-//~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
     type B = &'static Self::A;
-    //~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
 }
 
 fn main() {
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
index 6a8526f6aad..0aea30b1112 100644
--- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
@@ -1,33 +1,34 @@
-error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
+error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-1.rs:10:6
    |
 LL | impl Tr for () {}
    |      ^^
 
-error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-1.rs:28:6
    |
 LL | impl Tr for bool {
-   |      ^^
+   |      ^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
+error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-1.rs:35:6
    |
 LL | impl Tr for usize {
-   |      ^^
+   |      ^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-1.rs:30:5
    |
 LL |     type A = Box<Self::B>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
+error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
   --> $DIR/defaults-cyclic-fail-1.rs:37:5
    |
 LL |     type B = &'static Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0275`.
+Some errors have detailed explanations: E0271, E0275.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs
index 05091e3f498..edcd310908a 100644
--- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs
@@ -10,7 +10,7 @@ trait Tr {
 
 // ...but is an error in any impl that doesn't override at least one of the defaults
 impl Tr for () {}
-//~^ ERROR overflow evaluating the requirement
+//~^ ERROR type mismatch resolving `<() as Tr>::B == _`
 
 // As soon as at least one is redefined, it works:
 impl Tr for u8 {
@@ -28,16 +28,16 @@ impl Tr for u32 {
 
 // ...but only if this actually breaks the cycle
 impl Tr for bool {
-//~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
     type A = Box<Self::B>;
-    //~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
 }
 // (the error is shown twice for some reason)
 
 impl Tr for usize {
-//~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
     type B = &'static Self::A;
-    //~^ ERROR overflow evaluating the requirement
+    //~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
 }
 
 fn main() {
diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
index 78772df9638..f39021c30ed 100644
--- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
+++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
@@ -1,33 +1,33 @@
-error[E0275]: overflow evaluating the requirement `<() as Tr>::B`
+error[E0271]: type mismatch resolving `<() as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-2.rs:12:6
    |
 LL | impl Tr for () {}
-   |      ^^
+   |      ^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-2.rs:30:6
    |
 LL | impl Tr for bool {
-   |      ^^
+   |      ^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<usize as Tr>::B`
+error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-2.rs:37:6
    |
 LL | impl Tr for usize {
-   |      ^^
+   |      ^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<bool as Tr>::B`
+error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
   --> $DIR/defaults-cyclic-fail-2.rs:32:5
    |
 LL |     type A = Box<Self::B>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
-error[E0275]: overflow evaluating the requirement `<usize as Tr>::A`
+error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
   --> $DIR/defaults-cyclic-fail-2.rs:39:5
    |
 LL |     type B = &'static Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs b/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs
new file mode 100644
index 00000000000..0fd2c707938
--- /dev/null
+++ b/src/test/ui/associated-types/normalize-cycle-in-eval-no-region.rs
@@ -0,0 +1,20 @@
+// Case that the fix for #74868 also allowed to compile
+
+// check-pass
+
+trait BoxedDsl {
+    type Output;
+}
+
+impl<T> BoxedDsl for T
+where
+    T: BoxedDsl,
+{
+    type Output = <T as BoxedDsl>::Output;
+}
+
+trait HandleUpdate {}
+
+impl<T> HandleUpdate for T where T: BoxedDsl<Output = ()> {}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/normalize-cycle-in-eval.rs b/src/test/ui/associated-types/normalize-cycle-in-eval.rs
new file mode 100644
index 00000000000..dff4c9051f4
--- /dev/null
+++ b/src/test/ui/associated-types/normalize-cycle-in-eval.rs
@@ -0,0 +1,43 @@
+// regression test for #74868
+
+// check-pass
+
+trait BoxedDsl<'a> {
+    type Output;
+}
+
+impl<'a, T> BoxedDsl<'a> for T
+where
+    T: BoxedDsl<'a>,
+{
+    type Output = <T as BoxedDsl<'a>>::Output;
+}
+
+// Showing this trait is wf requires proving
+// Self: HandleUpdate
+//
+// The impl below is a candidate for this projection, as well as the `Self:
+// HandleUpdate` bound in the environment.
+// We evaluate both candidates to see if we need to consider both applicable.
+// Evaluating the impl candidate requires evaluating
+// <T as BoxedDsl<'static>>::Output == ()
+// The above impl cause normalizing the above type normalize to itself.
+//
+// This previously compiled because we would generate a new region
+// variable each time around the cycle, and evaluation would eventually return
+// `EvaluatedToErr` from the `Self: Sized` in the impl, which would in turn
+// leave the bound as the only candidate.
+//
+// #73452 changed this so that region variables are canonicalized when we
+// normalize, which means that the projection cycle is detected before
+// evaluation returns EvaluatedToErr. The cycle resulted in an error being
+// emitted immediately, causing this to fail to compile.
+//
+// To fix this, normalization doesn't directly emit errors when it finds a
+// cycle, instead letting the caller handle it. This restores the original
+// behavior.
+trait HandleUpdate {}
+
+impl<T> HandleUpdate for T where T: BoxedDsl<'static, Output = ()> {}
+
+fn main() {}
diff --git a/src/test/ui/auto-traits/issue-23080-2.rs b/src/test/ui/auto-traits/issue-23080-2.rs
index 7f6b9e3fba7..867f24f8cb4 100644
--- a/src/test/ui/auto-traits/issue-23080-2.rs
+++ b/src/test/ui/auto-traits/issue-23080-2.rs
@@ -1,5 +1,3 @@
-//~ ERROR
-
 #![feature(optin_builtin_traits)]
 #![feature(negative_impls)]
 
diff --git a/src/test/ui/auto-traits/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr
index 48ce09aaa34..efeceafdd2a 100644
--- a/src/test/ui/auto-traits/issue-23080-2.stderr
+++ b/src/test/ui/auto-traits/issue-23080-2.stderr
@@ -1,17 +1,11 @@
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/issue-23080-2.rs:7:10
+  --> $DIR/issue-23080-2.rs:5:10
    |
 LL | unsafe auto trait Trait {
    |                   ----- auto trait cannot have items
 LL |     type Output;
    |          ^^^^^^
 
-error[E0275]: overflow evaluating the requirement `<() as Trait>::Output`
-   |
-   = note: required because of the requirements on the impl of `Trait` for `()`
-   = note: required because of the requirements on the impl of `Trait` for `()`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0275, E0380.
-For more information about an error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0380`.
diff --git a/src/test/ui/issues/issue-21946.rs b/src/test/ui/issues/issue-21946.rs
index 2d99769cfa3..0a9f8f50bdc 100644
--- a/src/test/ui/issues/issue-21946.rs
+++ b/src/test/ui/issues/issue-21946.rs
@@ -5,9 +5,9 @@ trait Foo {
 struct FooStruct;
 
 impl Foo for FooStruct {
-//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
+    //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
     type A = <FooStruct as Foo>::A;
-    //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
+    //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr
index 5ac49f61543..582ce393d7f 100644
--- a/src/test/ui/issues/issue-21946.stderr
+++ b/src/test/ui/issues/issue-21946.stderr
@@ -1,10 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
+error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
   --> $DIR/issue-21946.rs:7:6
    |
 LL | impl Foo for FooStruct {
    |      ^^^
 
-error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
+error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
   --> $DIR/issue-21946.rs:9:5
    |
 LL |     type A = <FooStruct as Foo>::A;
diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr
index 1b752b7afe2..4e2e837c07c 100644
--- a/src/test/ui/issues/issue-23122-1.stderr
+++ b/src/test/ui/issues/issue-23122-1.stderr
@@ -1,10 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
+error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
   --> $DIR/issue-23122-1.rs:7:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |               ^^^^
 
-error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
+error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
   --> $DIR/issue-23122-1.rs:9:5
    |
 LL |     type Next = <GetNext<T> as Next>::Next;
diff --git a/src/test/ui/mir/issue-75419-validation-impl-trait.rs b/src/test/ui/mir/issue-75419-validation-impl-trait.rs
new file mode 100644
index 00000000000..a8741befb0c
--- /dev/null
+++ b/src/test/ui/mir/issue-75419-validation-impl-trait.rs
@@ -0,0 +1,13 @@
+// build-pass
+
+// This used to fail MIR validation due to the types on both sides of
+// an assignment not being equal.
+// The failure doesn't occur with a check-only build.
+
+fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator<Item = &'a T> {
+    xs.iter()
+}
+
+fn main() {
+    iter_slice::<()> as fn(_) -> _;
+}
diff --git a/src/test/ui/typeck/issue-74933.rs b/src/test/ui/typeck/issue-74933.rs
new file mode 100644
index 00000000000..4b6c173b8ce
--- /dev/null
+++ b/src/test/ui/typeck/issue-74933.rs
@@ -0,0 +1,38 @@
+// check-pass
+//
+// rust-lang/rust#74933: Lifetime error when indexing with borrowed index
+
+use std::ops::{Index, IndexMut};
+
+struct S(V);
+struct K<'a>(&'a ());
+struct V;
+
+impl<'a> Index<&'a K<'a>> for S {
+    type Output = V;
+
+    fn index(&self, _: &'a K<'a>) -> &V {
+        &self.0
+    }
+}
+
+impl<'a> IndexMut<&'a K<'a>> for S {
+    fn index_mut(&mut self, _: &'a K<'a>) -> &mut V {
+        &mut self.0
+    }
+}
+
+impl V {
+    fn foo(&mut self) {}
+}
+
+fn test(s: &mut S, k: &K<'_>) {
+    s[k] = V;
+    s[k].foo();
+}
+
+fn main() {
+    let mut s = S(V);
+    let k = K(&());
+    test(&mut s, &k);
+}
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 72437e07004..88081efabd3 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -32,8 +32,7 @@ MAINTAINERS = {
     'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
     'rust-by-example': {'steveklabnik', 'marioidival'},
     'embedded-book': {
-        'adamgreig', 'andre-richter', 'jamesmunns', 'korken89',
-        'ryankurte', 'thejpster', 'therealprof',
+        'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof',
     },
     'edition-guide': {'ehuss', 'steveklabnik'},
     'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'},