about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-07-24 21:59:43 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2020-10-06 11:19:31 +0100
commit596d6c4b3b5e86e024cd02f7221749ee6958bec6 (patch)
tree0b4424c4e35cf9bf356ea0637d3d603ab4d26795
parent34e5a4992c920ce9e68c333621f3d4c967c012c4 (diff)
downloadrust-596d6c4b3b5e86e024cd02f7221749ee6958bec6.tar.gz
rust-596d6c4b3b5e86e024cd02f7221749ee6958bec6.zip
Avoid cycle with projections from object types
Normalizing `<dyn Iterator<Item = ()> as Iterator>::Item` no longer
requires selecting `dyn Iterator<Item = ()>: Iterator`. This was
previously worked around by using a special type-folder to normalize
things.
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs207
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs176
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.rs23
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.stderr24
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.rs17
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.stderr24
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs23
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr24
-rw-r--r--src/test/ui/traits/cycle-cache-err-60010.rs3
-rw-r--r--src/test/ui/traits/cycle-cache-err-60010.stderr18
11 files changed, 193 insertions, 350 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index d52e5419100..71a4623cd62 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1,6 +1,5 @@
 //! Code for projecting associated types out of trait references.
 
-use super::elaborate_predicates;
 use super::specialization_graph;
 use super::translate_substs;
 use super::util;
@@ -53,13 +52,16 @@ pub enum ProjectionTyError<'tcx> {
 
 #[derive(PartialEq, Eq, Debug)]
 enum ProjectionTyCandidate<'tcx> {
-    // from a where-clause in the env or object type
+    /// From a where-clause in the env or object type
     ParamEnv(ty::PolyProjectionPredicate<'tcx>),
 
-    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+    /// From the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
     TraitDef(ty::PolyProjectionPredicate<'tcx>),
 
-    // from a "impl" (or a "pseudo-impl" returned by select)
+    /// Bounds specified on an object type
+    Object(ty::PolyProjectionPredicate<'tcx>),
+
+    /// From a "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
 }
 
@@ -561,14 +563,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             } else {
                 obligations.extend(ty.obligations);
             }
-
-            obligations.push(get_paranoid_cache_value_obligation(
-                infcx,
-                param_env,
-                projection_ty,
-                cause,
-                depth,
-            ));
             return Ok(Some(ty.value));
         }
         Err(ProjectionCacheEntry::Error) => {
@@ -703,45 +697,6 @@ fn prune_cache_value_obligations<'a, 'tcx>(
     NormalizedTy { value: result.value, obligations }
 }
 
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> PredicateObligation<'tcx> {
-    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(infcx.tcx),
-    }
-}
-
 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
 /// hold. In various error cases, we cannot generate a valid
 /// normalized projection. Therefore, we create an inference variable
@@ -848,12 +803,21 @@ fn project_type<'cx, 'tcx>(
 
     assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
 
-    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+    assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates {
+        // Avoid normalization cycle from selection (see
+        // `assemble_candidates_from_object_ty`).
+        // FIXME(lazy_normalization): Lazy normalization should save us from
+        // having to do special case this.
+    } else {
+        assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+    };
 
     match candidates {
-        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
-            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
-        )),
+        ProjectionTyCandidateSet::Single(candidate) => {
+            Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate)))
+        }
         ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
             selcx
                 .tcx()
@@ -932,6 +896,53 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     )
 }
 
+/// In the case of a trait object like
+/// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
+/// predicate in the trait object.
+///
+/// We don't go through the select candidate for these bounds to avoid cycles:
+/// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
+/// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
+/// this then has to be normalized without having to prove
+/// `dyn Iterator<Item = ()>: Iterator` again.
+fn assemble_candidates_from_object_ty<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_object_ty(..)");
+
+    let tcx = selcx.tcx();
+
+    let self_ty = obligation_trait_ref.self_ty();
+    let object_ty = selcx.infcx().shallow_resolve(self_ty);
+    let data = match object_ty.kind {
+        ty::Dynamic(ref data, ..) => data,
+        ty::Infer(ty::TyVar(_)) => {
+            // If the self-type is an inference variable, then it MAY wind up
+            // being an object type, so induce an ambiguity.
+            candidate_set.mark_ambiguous();
+            return;
+        }
+        _ => return,
+    };
+    let env_predicates = data
+        .projection_bounds()
+        .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+        .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
+
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::Object,
+        env_predicates,
+        false,
+    );
+}
+
 fn assemble_candidates_from_predicates<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
@@ -1000,7 +1011,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
             super::ImplSource::Closure(_)
             | super::ImplSource::Generator(_)
             | super::ImplSource::FnPointer(_)
-            | super::ImplSource::Object(_)
             | super::ImplSource::TraitAlias(_) => {
                 debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source);
                 true
@@ -1125,6 +1135,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // in `assemble_candidates_from_param_env`.
                 false
             }
+            super::ImplSource::Object(_) => {
+                // Handled by the `Object` projection candidate. See
+                // `assemble_candidates_from_object_ty` for an explanation of
+                // why we special case object types.
+                false
+            }
             super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
@@ -1150,13 +1166,13 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 fn confirm_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate: ProjectionTyCandidate<'tcx>,
 ) -> Progress<'tcx> {
     debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
 
     let mut progress = match candidate {
-        ProjectionTyCandidate::ParamEnv(poly_projection) => {
+        ProjectionTyCandidate::ParamEnv(poly_projection)
+        | ProjectionTyCandidate::Object(poly_projection) => {
             confirm_param_env_candidate(selcx, obligation, poly_projection, false)
         }
 
@@ -1165,7 +1181,7 @@ fn confirm_candidate<'cx, 'tcx>(
         }
 
         ProjectionTyCandidate::Select(impl_source) => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source)
+            confirm_select_candidate(selcx, obligation, impl_source)
         }
     };
     // When checking for cycle during evaluation, we compare predicates with
@@ -1182,7 +1198,6 @@ fn confirm_candidate<'cx, 'tcx>(
 fn confirm_select_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
     impl_source: Selection<'tcx>,
 ) -> Progress<'tcx> {
     match impl_source {
@@ -1193,10 +1208,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
         super::ImplSource::DiscriminantKind(data) => {
             confirm_discriminant_kind_candidate(selcx, obligation, data)
         }
-        super::ImplSource::Object(_) => {
-            confirm_object_candidate(selcx, obligation, obligation_trait_ref)
-        }
-        super::ImplSource::AutoImpl(..)
+        super::ImplSource::Object(_)
+        | super::ImplSource::AutoImpl(..)
         | super::ImplSource::Param(..)
         | super::ImplSource::Builtin(..)
         | super::ImplSource::TraitAlias(..) =>
@@ -1211,72 +1224,6 @@ fn confirm_select_candidate<'cx, 'tcx>(
     }
 }
 
-fn confirm_object_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
-    let self_ty = obligation_trait_ref.self_ty();
-    let object_ty = selcx.infcx().shallow_resolve(self_ty);
-    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
-    let data = match object_ty.kind() {
-        ty::Dynamic(data, ..) => data,
-        _ => span_bug!(
-            obligation.cause.span,
-            "confirm_object_candidate called with non-object: {:?}",
-            object_ty
-        ),
-    };
-    let env_predicates = data
-        .projection_bounds()
-        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx()));
-    let env_predicate = {
-        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
-        // select only those projections that are actually projecting an
-        // item with the correct name
-
-        let env_predicates = env_predicates.filter_map(|o| match o.predicate.skip_binders() {
-            ty::PredicateAtom::Projection(data)
-                if data.projection_ty.item_def_id == obligation.predicate.item_def_id =>
-            {
-                Some(ty::Binder::bind(data))
-            }
-            _ => None,
-        });
-
-        // select those with a relevant trait-ref
-        let mut env_predicates = env_predicates.filter(|data| {
-            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
-            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
-                selcx
-                    .infcx()
-                    .at(&obligation.cause, obligation.param_env)
-                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                    .is_ok()
-            })
-        });
-
-        // select the first matching one; there really ought to be one or
-        // else the object type is not WF, since an object type should
-        // include all of its projections explicitly
-        match env_predicates.next() {
-            Some(env_predicate) => env_predicate,
-            None => {
-                debug!(
-                    "confirm_object_candidate: no env-predicate \
-                     found in object type `{:?}`; ill-formed",
-                    object_ty
-                );
-                return Progress::error(selcx.tcx());
-            }
-        }
-    };
-
-    confirm_param_env_candidate(selcx, obligation, env_predicate, false)
-}
-
 fn confirm_generator_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index e6fce78f269..1e68554fecf 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -9,11 +9,10 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
-use rustc_infer::infer::{self, InferOk};
-use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Ty};
 use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness};
 use rustc_span::def_id::DefId;
 
@@ -434,100 +433,54 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
         }
 
-        // Check supertraits hold
-        nested.extend(util::supertraits(tcx, obligation_trait_ref).skip(1).map(|super_trait| {
-            Obligation::new(
-                obligation.cause.clone(),
-                obligation.param_env,
-                super_trait.without_const().to_predicate(tcx),
-            )
-        }));
-
         let upcast_trait_ref = upcast_trait_ref.unwrap();
 
+        // Check supertraits hold
+        nested.extend(
+            tcx.super_predicates_of(trait_predicate.def_id())
+                .instantiate(tcx, trait_predicate.trait_ref.substs)
+                .predicates
+                .into_iter()
+                .map(|super_trait| {
+                    Obligation::new(obligation.cause.clone(), obligation.param_env, super_trait)
+                }),
+        );
+
         let assoc_types: Vec<_> = tcx
-            .associated_items(upcast_trait_ref.def_id())
+            .associated_items(trait_predicate.def_id())
             .in_definition_order()
             .filter_map(
                 |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
             )
             .collect();
 
-        if !assoc_types.is_empty() {
-            let predicates: Vec<_> =
-                data.iter()
-                    .filter_map(|pred| match pred {
-                        ty::ExistentialPredicate::Projection(proj) => {
-                            if assoc_types.contains(&proj.item_def_id) {
-                                match self.infcx.commit_if_ok(|_| {
-                                    self.infcx
-                                        .at(&obligation.cause, obligation.param_env)
-                                        .sup(
-                                            ty::Binder::dummy(
-                                                proj.trait_ref(tcx).with_self_ty(tcx, self_ty),
-                                            ),
-                                            upcast_trait_ref,
-                                        )
-                                        .map(|InferOk { obligations, .. }| obligations)
-                                        .map_err(|_| ())
-                                }) {
-                                    Ok(obligations) => {
-                                        nested.extend(obligations);
-                                        Some(proj)
-                                    }
-                                    Err(_) => None,
-                                }
-                            } else {
-                                None
-                            }
-                        }
-                        ty::ExistentialPredicate::AutoTrait(_)
-                        | ty::ExistentialPredicate::Trait(_) => None,
-                    })
-                    .collect();
-
-            let upcast_trait_ref = upcast_trait_ref
-                .no_bound_vars()
-                .expect("sup shouldn't return binder with bound vars");
-            let mut normalizer = ObjectAssociatedTypeNormalizer {
-                infcx: self.infcx,
-                object_ty: self_ty,
-                object_bounds: &predicates,
-                param_env: obligation.param_env,
-                cause: &obligation.cause,
-                nested: &mut nested,
-            };
-            for assoc_type in assoc_types {
-                if !tcx.generics_of(assoc_type).params.is_empty() {
-                    // FIXME(generic_associated_types) generate placeholders to
-                    // extend the trait substs.
-                    tcx.sess.span_fatal(
-                        obligation.cause.span,
-                        "generic associated types in trait objects are not supported yet",
-                    );
-                }
-                // This maybe belongs in wf, but that can't (doesn't) handle
-                // higher-ranked things.
-                // Prevent, e.g., `dyn Iterator<Item = str>`.
-                for bound in self.tcx().item_bounds(assoc_type) {
-                    let subst_bound = bound.subst(tcx, upcast_trait_ref.substs);
-                    // Normalize projections the trait object manually to
-                    // avoid evaluation overflow.
-                    let object_normalized = subst_bound.fold_with(&mut normalizer);
-                    let normalized_bound = normalize_with_depth_to(
-                        self,
-                        obligation.param_env,
-                        obligation.cause.clone(),
-                        obligation.recursion_depth + 1,
-                        &object_normalized,
-                        normalizer.nested,
-                    );
-                    normalizer.nested.push(Obligation::new(
-                        obligation.cause.clone(),
-                        obligation.param_env.clone(),
-                        normalized_bound,
-                    ));
-                }
+        for assoc_type in assoc_types {
+            if !tcx.generics_of(assoc_type).params.is_empty() {
+                // FIXME(generic_associated_types) generate placeholders to
+                // extend the trait substs.
+                tcx.sess.span_fatal(
+                    obligation.cause.span,
+                    "generic associated types in trait objects are not supported yet",
+                );
+            }
+            // This maybe belongs in wf, but that can't (doesn't) handle
+            // higher-ranked things.
+            // Prevent, e.g., `dyn Iterator<Item = str>`.
+            for bound in self.tcx().item_bounds(assoc_type) {
+                let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs);
+                let normalized_bound = normalize_with_depth_to(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    &subst_bound,
+                    &mut nested,
+                );
+                nested.push(Obligation::new(
+                    obligation.cause.clone(),
+                    obligation.param_env.clone(),
+                    normalized_bound,
+                ));
             }
         }
 
@@ -972,50 +925,3 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(ImplSourceBuiltinData { nested })
     }
 }
-
-struct ObjectAssociatedTypeNormalizer<'a, 'tcx> {
-    infcx: &'a infer::InferCtxt<'a, 'tcx>,
-    object_ty: Ty<'tcx>,
-    object_bounds: &'a [ty::ExistentialProjection<'tcx>],
-    param_env: ty::ParamEnv<'tcx>,
-    cause: &'a ObligationCause<'tcx>,
-    nested: &'a mut Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'tcx> TypeFolder<'tcx> for ObjectAssociatedTypeNormalizer<'_, 'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.has_projections() {
-            return t;
-        }
-        if let ty::Projection(proj) = t.kind {
-            if let ty::Dynamic(..) = proj.self_ty().kind {
-                for bound in self.object_bounds {
-                    if proj.item_def_id == bound.item_def_id {
-                        // FIXME(generic_associated_types): This isn't relating
-                        // the substs for the associated type.
-                        match self.infcx.commit_if_ok(|_| {
-                            self.infcx.at(self.cause, self.param_env).sub(
-                                bound
-                                    .with_self_ty(self.infcx.tcx, self.object_ty)
-                                    .projection_ty
-                                    .trait_ref(self.infcx.tcx),
-                                proj.trait_ref(self.infcx.tcx),
-                            )
-                        }) {
-                            Ok(InferOk { value: (), obligations }) => {
-                                self.nested.extend(obligations);
-                                return bound.ty;
-                            }
-                            Err(_) => {}
-                        }
-                    }
-                }
-            }
-        }
-        t.super_fold_with(self)
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 147b0c74d16..d0c0e658c92 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -441,8 +441,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<EvaluationResult, OverflowError> {
         debug!(
             "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})",
-            previous_stack.head(),
-            obligation
+            obligation,
+            previous_stack.head()
         );
 
         // `previous_stack` stores a `TraitObligation`, while `obligation` is
diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs
index 781cdb7286a..6de08f66d75 100644
--- a/src/test/ui/regions/regions-enum-not-wf.rs
+++ b/src/test/ui/regions/regions-enum-not-wf.rs
@@ -5,17 +5,18 @@
 #![allow(dead_code)]
 
 trait Dummy<'a> {
-  type Out;
+    type Out;
 }
 impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+    T: 'a,
 {
-  type Out = ();
+    type Out = ();
 }
 type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
 
 enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
 enum Ref2<'a, T> {
@@ -23,18 +24,18 @@ enum Ref2<'a, T> {
     Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
-enum RefOk<'a, T:'a> {
-    RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+    RefOkVariant1(&'a T),
 }
 
 // This is now well formed. RFC 2093
 enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a,T>)
+    RefIndirectVariant1(isize, RefOk<'a, T>),
 }
 
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-        //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+    //~^ the parameter type `T` may not live long enough [E0309]
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
index e32a36f72cd..36686eaf92f 100644
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ b/src/test/ui/regions/regions-enum-not-wf.stderr
@@ -1,13 +1,13 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:18:18
+  --> $DIR/regions-enum-not-wf.rs:19:18
    |
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
+LL |     Ref1Variant1(RequireOutlives<'a, T>),
    |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:23:25
+  --> $DIR/regions-enum-not-wf.rs:24:25
    |
 LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
@@ -16,25 +16,13 @@ LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
-   |  _|
-   | |
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:36:23
+  --> $DIR/regions-enum-not-wf.rs:37:23
    |
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
index e912805d855..9912e88c2ec 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -6,7 +6,8 @@ trait Project<'a, 'b> {
 }
 
 impl<'a, 'b> Project<'a, 'b> for ()
-    where 'a: 'b
+where
+    'a: 'b,
 {
     type Item = ();
 }
@@ -14,16 +15,18 @@ impl<'a, 'b> Project<'a, 'b> for ()
 // No error here, we have 'a: 'b. We used to report an error here
 // though, see https://github.com/rust-lang/rust/issues/45937.
 fn foo<'a: 'b, 'b>()
-    where <() as Project<'a, 'b>>::Item : Eq
+where
+    <() as Project<'a, 'b>>::Item: Eq,
 {
 }
 
 // Here we get an error: we need `'a: 'b`.
-fn bar<'a, 'b>() //~ ERROR cannot infer
-                 //~| ERROR cannot infer
-                 //~| ERROR cannot infer
-    where <() as Project<'a, 'b>>::Item : Eq
+fn bar<'a, 'b>()
+//~^ ERROR cannot infer
+//~| ERROR cannot infer
+where
+    <() as Project<'a, 'b>>::Item: Eq,
 {
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index 10ecb8d5262..24bf64261e9 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -1,5 +1,5 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
    |
 LL | / fn bar<'a, 'b>()
 LL | |
@@ -7,18 +7,18 @@ LL | |
 LL | |     where <() as Project<'a, 'b>>::Item : Eq
    | |____________________________________________^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
    |
 LL | fn bar<'a, 'b>()
    |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
    |
 LL | fn bar<'a, 'b>()
    |            ^^
 note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
    |
 LL | / fn bar<'a, 'b>()
 LL | |
@@ -64,24 +64,24 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
 LL | fn bar<'a, 'b>()
    |    ^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
    |
 LL | fn bar<'a, 'b>()
    |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
    |
 LL | fn bar<'a, 'b>()
    |            ^^
 note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
    |
 LL | fn bar<'a, 'b>()
    |    ^^^
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
index 781cdb7286a..6de08f66d75 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
@@ -5,17 +5,18 @@
 #![allow(dead_code)]
 
 trait Dummy<'a> {
-  type Out;
+    type Out;
 }
 impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+    T: 'a,
 {
-  type Out = ();
+    type Out = ();
 }
 type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
 
 enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
 enum Ref2<'a, T> {
@@ -23,18 +24,18 @@ enum Ref2<'a, T> {
     Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
-enum RefOk<'a, T:'a> {
-    RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+    RefOkVariant1(&'a T),
 }
 
 // This is now well formed. RFC 2093
 enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a,T>)
+    RefIndirectVariant1(isize, RefOk<'a, T>),
 }
 
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-        //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+    //~^ the parameter type `T` may not live long enough [E0309]
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
index e32a36f72cd..36686eaf92f 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -1,13 +1,13 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:18:18
+  --> $DIR/regions-enum-not-wf.rs:19:18
    |
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
+LL |     Ref1Variant1(RequireOutlives<'a, T>),
    |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:23:25
+  --> $DIR/regions-enum-not-wf.rs:24:25
    |
 LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
@@ -16,25 +16,13 @@ LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
-   |  _|
-   | |
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:36:23
+  --> $DIR/regions-enum-not-wf.rs:37:23
    |
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs
index 62d558fde88..98bfcb8d67b 100644
--- a/src/test/ui/traits/cycle-cache-err-60010.rs
+++ b/src/test/ui/traits/cycle-cache-err-60010.rs
@@ -24,7 +24,7 @@ struct Runtime<DB: Database> {
     _storage: Box<DB::Storage>,
 }
 struct SalsaStorage {
-    _parse: <ParseQuery as Query<RootDatabase>>::Data, //~ ERROR overflow
+    _parse: <ParseQuery as Query<RootDatabase>>::Data,
 }
 
 impl Database for RootDatabase {
@@ -67,6 +67,7 @@ pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 {
     // we used to fail to report an error here because we got the
     // caching wrong.
     SourceDatabase::parse(db);
+    //~^ ERROR overflow
     22
 }
 
diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr
index 25b1f427f3a..738b052a11e 100644
--- a/src/test/ui/traits/cycle-cache-err-60010.stderr
+++ b/src/test/ui/traits/cycle-cache-err-60010.stderr
@@ -1,10 +1,18 @@
-error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
-  --> $DIR/cycle-cache-err-60010.rs:27:13
+error[E0275]: overflow evaluating the requirement `SalsaStorage: std::panic::RefUnwindSafe`
+  --> $DIR/cycle-cache-err-60010.rs:69:5
    |
-LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn parse(&self) {
+   |     --------------- required by `SourceDatabase::parse`
+...
+LL |     SourceDatabase::parse(db);
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
+   = note: required because it appears within the type `*const SalsaStorage`
+   = note: required because it appears within the type `std::ptr::Unique<SalsaStorage>`
+   = note: required because it appears within the type `std::boxed::Box<SalsaStorage>`
+   = note: required because it appears within the type `Runtime<RootDatabase>`
+   = note: required because it appears within the type `RootDatabase`
+   = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
 
 error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
   --> $DIR/cycle-cache-err-60010.rs:31:20