about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-27 14:10:02 +0000
committerbors <bors@rust-lang.org>2023-07-27 14:10:02 +0000
commitb73e9a48aeeb44fa897ab820737dfd77c5076e01 (patch)
treea3a054841d43d9ebcc73675f4ed69ed3233786bb
parent49a16b64b0a288c744929d7c0458c048c3f4cbf0 (diff)
parent218e88e5d8f6503fade7bc7f669c3d7dd5f5de07 (diff)
downloadrust-b73e9a48aeeb44fa897ab820737dfd77c5076e01.tar.gz
rust-b73e9a48aeeb44fa897ab820737dfd77c5076e01.zip
Auto merge of #114130 - GuillaumeGomez:rollup-69ihuaj, r=GuillaumeGomez
Rollup of 7 pull requests

Successful merges:

 - #114032 (typos)
 - #114059 (rustdoc: fix cross-crate `impl Sized` & `impl ?Sized`)
 - #114088 (Bump syn dependency)
 - #114091 (docs: fmt::Debug*: Fix comments for finish method.)
 - #114109 (Docs: Fix URL for `rmatches`)
 - #114117 (Restore region uniquification in the new solver 🎉  )
 - #114123 (Turns out opaque types can have hidden types registered during mir validation)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock38
-rw-r--r--compiler/rustc_const_eval/src/util/compare_types.rs15
-rw-r--r--compiler/rustc_macros/Cargo.toml3
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs25
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs2
-rw-r--r--library/core/src/fmt/builders.rs6
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--src/librustdoc/clean/mod.rs80
-rw-r--r--src/librustdoc/clean/types.rs17
-rw-r--r--src/librustdoc/html/format.rs35
-rw-r--r--src/tools/compiletest/src/header/cfg.rs4
-rw-r--r--tests/rustdoc/extern-impl-trait.rs2
-rw-r--r--tests/rustdoc/impl-everywhere.rs2
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/impl-sized.rs21
-rw-r--r--tests/rustdoc/inline_cross/impl-sized.rs27
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs8
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr52
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs30
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr273
-rw-r--r--tests/ui/impl-trait/autoderef.rs2
-rw-r--r--tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs32
-rw-r--r--tests/ui/type-alias-impl-trait/broken_mir.rs16
22 files changed, 420 insertions, 272 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fce2869ef42..45959c039e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -220,7 +220,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -502,7 +502,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -527,7 +527,7 @@ dependencies = [
  "regex",
  "rustc_tools_util",
  "serde",
- "syn 2.0.8",
+ "syn 2.0.27",
  "tempfile",
  "termize",
  "tester",
@@ -842,7 +842,7 @@ version = "0.1.73"
 dependencies = [
  "itertools",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -943,7 +943,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -1309,7 +1309,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -2456,7 +2456,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -2643,7 +2643,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -3586,7 +3586,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
  "unic-langid",
 ]
 
@@ -3855,7 +3855,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
  "synstructure 0.13.0",
 ]
 
@@ -4462,7 +4462,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -4629,7 +4629,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -4910,9 +4910,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.8"
+version = "2.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4939,7 +4939,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
  "unicode-xid",
 ]
 
@@ -5089,7 +5089,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -5310,7 +5310,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
 ]
 
 [[package]]
@@ -5740,7 +5740,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
  "wasm-bindgen-shared",
 ]
 
@@ -5774,7 +5774,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.27",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index 88d4f5e715c..83376c8e992 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -57,12 +57,15 @@ pub fn is_subtype<'tcx>(
     // we would get unification errors because we're unable to look into opaque types,
     // even if they're constrained in our current function.
     for (key, ty) in infcx.take_opaque_types() {
-        span_bug!(
-            ty.hidden_type.span,
-            "{}, {}",
-            tcx.type_of(key.def_id).instantiate(tcx, key.args),
-            ty.hidden_type.ty
-        );
+        let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
+        if hidden_ty != ty.hidden_type.ty {
+            span_bug!(
+                ty.hidden_type.span,
+                "{}, {}",
+                tcx.type_of(key.def_id).instantiate(tcx, key.args),
+                ty.hidden_type.ty
+            );
+        }
     }
     errors.is_empty()
 }
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 16c4a850012..17651ce9598 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -8,7 +8,6 @@ proc-macro = true
 
 [dependencies]
 synstructure = "0.13.0"
-# FIXME(Nilstrieb): Updating this causes changes in the diagnostics output.
-syn = { version = "=2.0.8", features = ["full"] }
+syn = { version = "2.0.9", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 255620489ff..88771f90756 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -125,9 +125,8 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
         // - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6
         // - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: -
         //
-        // This algorithm runs in `O(nm)` where `n` is the number of different universe
-        // indices in the input and `m` is the number of canonical variables.
-        // This should be fine as both `n` and `m` are expected to be small.
+        // This algorithm runs in `O(n²)` where `n` is the number of different universe
+        // indices in the input. This should be fine as `n` is expected to be small.
         let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
         let mut existential_in_new_uv = false;
         let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
@@ -263,14 +262,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
             ty::ReError(_) => return r,
         };
 
-        let var = ty::BoundVar::from(
-            self.variables.iter().position(|&v| v == r.into()).unwrap_or_else(|| {
-                let var = self.variables.len();
-                self.variables.push(r.into());
-                self.primitive_var_infos.push(CanonicalVarInfo { kind });
-                var
-            }),
-        );
+        let existing_bound_var = match self.canonicalize_mode {
+            CanonicalizeMode::Input => None,
+            CanonicalizeMode::Response { .. } => {
+                self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
+            }
+        };
+        let var = existing_bound_var.unwrap_or_else(|| {
+            let var = ty::BoundVar::from(self.variables.len());
+            self.variables.push(r.into());
+            self.primitive_var_infos.push(CanonicalVarInfo { kind });
+            var
+        });
         let br = ty::BoundRegion { var, kind: BrAnon(None) };
         ty::Region::new_late_bound(self.interner(), self.binder_index, br)
     }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index f48a992d327..9e3b0bbc4fb 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -344,7 +344,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             Ok(response) => response,
         };
 
-        let has_changed = !canonical_response.value.var_values.is_identity()
+        let has_changed = !canonical_response.value.var_values.is_identity_modulo_regions()
             || !canonical_response.value.external_constraints.opaque_types.is_empty();
         let (certainty, nested_goals) = match self.instantiate_and_apply_query_response(
             goal.param_env,
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 36f49d51ca6..d2c9f980042 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -518,7 +518,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         fmt.debug_set()
     ///            .entries(self.0.iter())
-    ///            .finish() // Ends the struct formatting.
+    ///            .finish() // Ends the set formatting.
     ///     }
     /// }
     ///
@@ -648,7 +648,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         fmt.debug_list()
     ///            .entries(self.0.iter())
-    ///            .finish() // Ends the struct formatting.
+    ///            .finish() // Ends the list formatting.
     ///     }
     /// }
     ///
@@ -905,7 +905,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     ///         fmt.debug_map()
     ///            .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
-    ///            .finish() // Ends the struct formatting.
+    ///            .finish() // Ends the map formatting.
     ///     }
     /// }
     ///
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 9a93bb72903..07a5990e595 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1666,7 +1666,7 @@ impl str {
     /// If the pattern allows a reverse search but its results might differ
     /// from a forward search, the [`rmatches`] method can be used.
     ///
-    /// [`rmatches`]: str::matches
+    /// [`rmatches`]: str::rmatches
     ///
     /// # Examples
     ///
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a57854837d5..e4bb392aef7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -804,10 +804,10 @@ fn clean_ty_generics<'tcx>(
     let where_predicates = preds
         .predicates
         .iter()
-        .flat_map(|(p, _)| {
+        .flat_map(|(pred, _)| {
             let mut projection = None;
             let param_idx = (|| {
-                let bound_p = p.kind();
+                let bound_p = pred.kind();
                 match bound_p.skip_binder() {
                     ty::ClauseKind::Trait(pred) => {
                         if let ty::Param(param) = pred.self_ty().kind() {
@@ -832,33 +832,26 @@ fn clean_ty_generics<'tcx>(
             })();
 
             if let Some(param_idx) = param_idx
-                && let Some(b) = impl_trait.get_mut(&param_idx.into())
+                && let Some(bounds) = impl_trait.get_mut(&param_idx.into())
             {
-                let p: WherePredicate = clean_predicate(*p, cx)?;
+                let pred = clean_predicate(*pred, cx)?;
 
-                b.extend(
-                    p.get_bounds()
+                bounds.extend(
+                    pred.get_bounds()
                         .into_iter()
                         .flatten()
                         .cloned()
-                        .filter(|b| !b.is_sized_bound(cx)),
                 );
 
-                let proj = projection.map(|p| {
-                    (
-                        clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
-                        p.map_bound(|p| p.term),
-                    )
-                });
-                if let Some(((_, trait_did, name), rhs)) = proj
-                    .as_ref()
-                    .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
+                if let Some(proj) = projection
+                    && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None)
+                    && let Some((_, trait_did, name)) = lhs.projection()
                 {
                     impl_trait_proj.entry(param_idx).or_default().push((
                         trait_did,
                         name,
-                        *rhs,
-                        p.get_bound_params()
+                        proj.map_bound(|p| p.term),
+                        pred.get_bound_params()
                             .into_iter()
                             .flatten()
                             .cloned()
@@ -869,13 +862,32 @@ fn clean_ty_generics<'tcx>(
                 return None;
             }
 
-            Some(p)
+            Some(pred)
         })
         .collect::<Vec<_>>();
 
     for (param, mut bounds) in impl_trait {
+        let mut has_sized = false;
+        bounds.retain(|b| {
+            if b.is_sized_bound(cx) {
+                has_sized = true;
+                false
+            } else {
+                true
+            }
+        });
+        if !has_sized {
+            bounds.push(GenericBound::maybe_sized(cx));
+        }
+
         // Move trait bounds to the front.
-        bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
+        bounds.sort_by_key(|b| !b.is_trait_bound());
+
+        // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
+        // Since all potential trait bounds are at the front we can just check the first bound.
+        if bounds.first().map_or(true, |b| !b.is_trait_bound()) {
+            bounds.insert(0, GenericBound::sized(cx));
+        }
 
         let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
         if let Some(proj) = impl_trait_proj.remove(&idx) {
@@ -897,7 +909,7 @@ fn clean_ty_generics<'tcx>(
     // implicit `Sized` bound unless removed with `?Sized`.
     // However, in the list of where-predicates below, `Sized` appears like a
     // normal bound: It's either present (the type is sized) or
-    // absent (the type is unsized) but never *maybe* (i.e. `?Sized`).
+    // absent (the type might be unsized) but never *maybe* (i.e. `?Sized`).
     //
     // This is unsuitable for rendering.
     // Thus, as a first step remove all `Sized` bounds that should be implicit.
@@ -908,8 +920,8 @@ fn clean_ty_generics<'tcx>(
     let mut sized_params = FxHashSet::default();
     where_predicates.retain(|pred| {
         if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
-        && *g != kw::SelfUpper
-        && bounds.iter().any(|b| b.is_sized_bound(cx))
+            && *g != kw::SelfUpper
+            && bounds.iter().any(|b| b.is_sized_bound(cx))
         {
             sized_params.insert(*g);
             false
@@ -2119,7 +2131,6 @@ fn clean_middle_opaque_bounds<'tcx>(
     cx: &mut DocContext<'tcx>,
     bounds: Vec<ty::Clause<'tcx>>,
 ) -> Type {
-    let mut regions = vec![];
     let mut has_sized = false;
     let mut bounds = bounds
         .iter()
@@ -2128,10 +2139,7 @@ fn clean_middle_opaque_bounds<'tcx>(
             let trait_ref = match bound_predicate.skip_binder() {
                 ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
                 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
-                    if let Some(r) = clean_middle_region(reg) {
-                        regions.push(GenericBound::Outlives(r));
-                    }
-                    return None;
+                    return clean_middle_region(reg).map(GenericBound::Outlives);
                 }
                 _ => return None,
             };
@@ -2167,10 +2175,20 @@ fn clean_middle_opaque_bounds<'tcx>(
             Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
         })
         .collect::<Vec<_>>();
-    bounds.extend(regions);
-    if !has_sized && !bounds.is_empty() {
-        bounds.insert(0, GenericBound::maybe_sized(cx));
+
+    if !has_sized {
+        bounds.push(GenericBound::maybe_sized(cx));
     }
+
+    // Move trait bounds to the front.
+    bounds.sort_by_key(|b| !b.is_trait_bound());
+
+    // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
+    // Since all potential trait bounds are at the front we can just check the first bound.
+    if bounds.first().map_or(true, |b| !b.is_trait_bound()) {
+        bounds.insert(0, GenericBound::sized(cx));
+    }
+
     ImplTrait(bounds)
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ddef165a054..647fbcdc3d7 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1219,15 +1219,24 @@ pub(crate) enum GenericBound {
 }
 
 impl GenericBound {
+    pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
+        Self::sized_with(cx, hir::TraitBoundModifier::None)
+    }
+
     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
+        Self::sized_with(cx, hir::TraitBoundModifier::Maybe)
+    }
+
+    fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
         let empty = ty::Binder::dummy(ty::GenericArgs::empty());
         let path = external_path(cx, did, false, ThinVec::new(), empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
-        GenericBound::TraitBound(
-            PolyTrait { trait_: path, generic_params: Vec::new() },
-            hir::TraitBoundModifier::Maybe,
-        )
+        GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier)
+    }
+
+    pub(crate) fn is_trait_bound(&self) -> bool {
+        matches!(self, Self::TraitBound(..))
     }
 
     pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index f60f40267d6..eb5d3c88570 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1102,22 +1102,35 @@ fn fmt_type<'cx>(
             };
             let m = mutability.print_with_space();
             let amp = if f.alternate() { "&" } else { "&amp;" };
-            match **ty {
+
+            if let clean::Generic(name) = **ty {
+                return primitive_link(
+                    f,
+                    PrimitiveType::Reference,
+                    &format!("{amp}{lt}{m}{name}"),
+                    cx,
+                );
+            }
+
+            write!(f, "{amp}{lt}{m}")?;
+
+            let needs_parens = match **ty {
                 clean::DynTrait(ref bounds, ref trait_lt)
                     if bounds.len() > 1 || trait_lt.is_some() =>
                 {
-                    write!(f, "{}{}{}(", amp, lt, m)?;
-                    fmt_type(ty, f, use_absolute, cx)?;
-                    write!(f, ")")
-                }
-                clean::Generic(name) => {
-                    primitive_link(f, PrimitiveType::Reference, &format!("{amp}{lt}{m}{name}"), cx)
-                }
-                _ => {
-                    write!(f, "{}{}{}", amp, lt, m)?;
-                    fmt_type(ty, f, use_absolute, cx)
+                    true
                 }
+                clean::ImplTrait(ref bounds) if bounds.len() > 1 => true,
+                _ => false,
+            };
+            if needs_parens {
+                f.write_str("(")?;
             }
+            fmt_type(ty, f, use_absolute, cx)?;
+            if needs_parens {
+                f.write_str(")")?;
+            }
+            Ok(())
         }
         clean::ImplTrait(ref bounds) => {
             if f.alternate() {
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index 86a749b935d..77c2866b366 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -112,7 +112,7 @@ pub(super) fn parse_cfg_name_directive<'a>(
             (config.target == "wasm32-unknown-unknown").then_some("emscripten"),
         ],
         allowed_names: &target_cfgs.all_oses,
-        message: "when the operative system is {name}"
+        message: "when the operating system is {name}"
     }
     condition! {
         name: &target_cfg.env,
@@ -122,7 +122,7 @@ pub(super) fn parse_cfg_name_directive<'a>(
     condition! {
         name: &target_cfg.os_and_env(),
         allowed_names: &target_cfgs.all_oses_and_envs,
-        message: "when the operative system and target environment are {name}"
+        message: "when the operating system and target environment are {name}"
     }
     condition! {
         name: &target_cfg.abi,
diff --git a/tests/rustdoc/extern-impl-trait.rs b/tests/rustdoc/extern-impl-trait.rs
index 8ab026afd1b..4d8672305a7 100644
--- a/tests/rustdoc/extern-impl-trait.rs
+++ b/tests/rustdoc/extern-impl-trait.rs
@@ -7,5 +7,5 @@ extern crate extern_impl_trait;
 // @has 'foo/struct.X.html' '//h4[@class="code-header"]' "impl Foo<Associated = ()> + 'a"
 pub use extern_impl_trait::X;
 
-// @has 'foo/struct.Y.html' '//h4[@class="code-header"]' "impl ?Sized + Foo<Associated = ()> + 'a"
+// @has 'foo/struct.Y.html' '//h4[@class="code-header"]' "impl Foo<Associated = ()> + ?Sized + 'a"
 pub use extern_impl_trait::Y;
diff --git a/tests/rustdoc/impl-everywhere.rs b/tests/rustdoc/impl-everywhere.rs
index 44885d4301f..2311c806c18 100644
--- a/tests/rustdoc/impl-everywhere.rs
+++ b/tests/rustdoc/impl-everywhere.rs
@@ -25,6 +25,6 @@ pub fn foo_foo() -> impl Foo + Foo2 {
     Bar
 }
 
-// @has foo/fn.foo_foo_foo.html '//section[@id="main-content"]//pre' "x: &'x impl Foo + Foo2"
+// @has foo/fn.foo_foo_foo.html '//section[@id="main-content"]//pre' "x: &'x (impl Foo + Foo2)"
 pub fn foo_foo_foo<'x>(_x: &'x (impl Foo + Foo2)) {
 }
diff --git a/tests/rustdoc/inline_cross/auxiliary/impl-sized.rs b/tests/rustdoc/inline_cross/auxiliary/impl-sized.rs
new file mode 100644
index 00000000000..65f72a3b9ac
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/impl-sized.rs
@@ -0,0 +1,21 @@
+use std::fmt::Debug;
+
+pub fn sized(x: impl Sized) -> impl Sized {
+    x
+}
+
+pub fn sized_outlives<'a>(x: impl Sized + 'a) -> impl Sized + 'a {
+    x
+}
+
+pub fn maybe_sized(x: &impl ?Sized) -> &impl ?Sized {
+    x
+}
+
+pub fn debug_maybe_sized(x: &(impl Debug + ?Sized)) -> &(impl Debug + ?Sized) {
+    x
+}
+
+pub fn maybe_sized_outlives<'t>(x: &(impl ?Sized + 't)) -> &(impl ?Sized + 't) {
+    x
+}
diff --git a/tests/rustdoc/inline_cross/impl-sized.rs b/tests/rustdoc/inline_cross/impl-sized.rs
new file mode 100644
index 00000000000..82bdce47478
--- /dev/null
+++ b/tests/rustdoc/inline_cross/impl-sized.rs
@@ -0,0 +1,27 @@
+#![crate_name = "user"]
+
+// aux-crate:impl_sized=impl-sized.rs
+// edition:2021
+
+// @has user/fn.sized.html
+// @has - '//pre[@class="rust item-decl"]' "sized(x: impl Sized) -> impl Sized"
+pub use impl_sized::sized;
+
+// @has user/fn.sized_outlives.html
+// @has - '//pre[@class="rust item-decl"]' \
+//     "sized_outlives<'a>(x: impl Sized + 'a) -> impl Sized + 'a"
+pub use impl_sized::sized_outlives;
+
+// @has user/fn.maybe_sized.html
+// @has - '//pre[@class="rust item-decl"]' "maybe_sized(x: &impl ?Sized) -> &impl ?Sized"
+pub use impl_sized::maybe_sized;
+
+// @has user/fn.debug_maybe_sized.html
+// @has - '//pre[@class="rust item-decl"]' \
+//     "debug_maybe_sized(x: &(impl Debug + ?Sized)) -> &(impl Debug + ?Sized)"
+pub use impl_sized::debug_maybe_sized;
+
+// @has user/fn.maybe_sized_outlives.html
+// @has - '//pre[@class="rust item-decl"]' \
+//     "maybe_sized_outlives<'t>(x: &(impl ?Sized + 't)) -> &(impl ?Sized + 't)"
+pub use impl_sized::maybe_sized_outlives;
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index ffbefce48d3..c30120e5cf3 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -53,7 +53,7 @@ enum DiagnosticOnEnum {
 #[derive(Diagnostic)]
 #[diag(no_crate_example, code = "E0123")]
 #[diag = "E0123"]
-//~^ ERROR expected parentheses: #[diag(...)]
+//~^ ERROR failed to resolve: maybe a missing crate `core`
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
@@ -644,7 +644,7 @@ struct MissingCodeInSuggestion {
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
 #[multipart_suggestion()]
 //~^ ERROR cannot find attribute `multipart_suggestion` in this scope
-//~| ERROR unexpected end of input, unexpected token in nested attribute, expected ident
+//~| ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 struct MultipartSuggestion {
     #[multipart_suggestion(no_crate_suggestion)]
     //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
@@ -797,7 +797,7 @@ struct SuggestionsNoItem {
 struct SuggestionsInvalidItem {
     #[suggestion(code(foo))]
     //~^ ERROR `code(...)` must contain only string literals
-    //~| ERROR unexpected token
+    //~| ERROR failed to resolve: maybe a missing crate `core`
     sub: Span,
 }
 
@@ -805,7 +805,7 @@ struct SuggestionsInvalidItem {
 #[diag(no_crate_example)]
 struct SuggestionsInvalidLiteral {
     #[suggestion(code = 3)]
-    //~^ ERROR expected string literal
+    //~^ ERROR failed to resolve: maybe a missing crate `core`
     sub: Span,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 1398f9c96bf..ca09f1f0153 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -20,12 +20,6 @@ LL |     Bar,
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: expected parentheses: #[diag(...)]
-  --> $DIR/diagnostic-derive.rs:55:8
-   |
-LL | #[diag = "E0123"]
-   |        ^
-
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:60:1
    |
@@ -477,6 +471,14 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:645:1
+   |
+LL | #[multipart_suggestion()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider creating a `Subdiagnostic` instead
+
+error: `#[multipart_suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:649:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
@@ -484,12 +486,6 @@ LL |     #[multipart_suggestion(no_crate_suggestion)]
    |
    = help: consider creating a `Subdiagnostic` instead
 
-error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/diagnostic-derive.rs:645:24
-   |
-LL | #[multipart_suggestion()]
-   |                        ^
-
 error: `#[suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:657:1
    |
@@ -550,18 +546,6 @@ error: `code(...)` must contain only string literals
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
-error: unexpected token
-  --> $DIR/diagnostic-derive.rs:798:23
-   |
-LL |     #[suggestion(code(foo))]
-   |                       ^^^
-
-error: expected string literal
-  --> $DIR/diagnostic-derive.rs:807:25
-   |
-LL |     #[suggestion(code = 3)]
-   |                         ^
-
 error: `#[suggestion(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:822:5
    |
@@ -572,6 +556,24 @@ LL |     #[suggestion(no_crate_suggestion, code = "")]
    = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`
    = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
 
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/diagnostic-derive.rs:55:8
+   |
+LL | #[diag = "E0123"]
+   |        ^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/diagnostic-derive.rs:798:23
+   |
+LL |     #[suggestion(code(foo))]
+   |                       ^^^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/diagnostic-derive.rs:807:25
+   |
+LL |     #[suggestion(code = 3)]
+   |                         ^ maybe a missing crate `core`?
+
 error: cannot find attribute `nonsense` in this scope
   --> $DIR/diagnostic-derive.rs:60:3
    |
@@ -656,5 +658,5 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
 
 error: aborting due to 84 previous errors
 
-Some errors have detailed explanations: E0277, E0425.
+Some errors have detailed explanations: E0277, E0425, E0433.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 38af5b0f9fb..dd0f7a7efb7 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -95,7 +95,8 @@ struct G {
 
 #[derive(Subdiagnostic)]
 #[label("...")]
-//~^ ERROR unexpected literal in nested attribute, expected ident
+//~^ ERROR failed to resolve: maybe a missing crate `core`?
+//~| NOTE maybe a missing crate `core`?
 struct H {
     #[primary_span]
     span: Span,
@@ -134,7 +135,7 @@ struct L {
 
 #[derive(Subdiagnostic)]
 #[label()]
-//~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
+//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
 struct M {
     #[primary_span]
     span: Span,
@@ -310,7 +311,8 @@ struct AB {
 
 #[derive(Subdiagnostic)]
 union AC {
-    //~^ ERROR unexpected unsupported untagged union
+    //~^ ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span: u32,
     b: u64,
 }
@@ -556,7 +558,7 @@ struct BBb {
 #[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
 struct BBc {
     #[suggestion_part()]
-    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
     span1: Span,
 }
 
@@ -576,11 +578,12 @@ struct BD {
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
     span1: Span,
     #[suggestion_part()]
-    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
     span2: Span,
     #[suggestion_part(foo = "bar")]
     //~^ ERROR `code` is the only valid nested attribute
-    //~| ERROR expected `,`
+    //~| ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span4: Span,
     #[suggestion_part(code = "...")]
     //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -672,7 +675,8 @@ enum BL {
 struct BM {
     #[suggestion_part(code("foo"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
-    //~| ERROR unexpected token
+    //~| ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span: Span,
     r#type: String,
 }
@@ -682,7 +686,8 @@ struct BM {
 struct BN {
     #[suggestion_part(code("foo", "bar"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
-    //~| ERROR unexpected token
+    //~| ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span: Span,
     r#type: String,
 }
@@ -692,7 +697,8 @@ struct BN {
 struct BO {
     #[suggestion_part(code(3))]
     //~^ ERROR expected exactly one string literal for `code = ...`
-    //~| ERROR unexpected token
+    //~| ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span: Span,
     r#type: String,
 }
@@ -713,7 +719,8 @@ struct BP {
 #[multipart_suggestion(no_crate_example)]
 struct BQ {
     #[suggestion_part(code = 3)]
-    //~^ ERROR expected string literal
+    //~^ ERROR failed to resolve: maybe a missing crate `core`?
+    //~| NOTE maybe a missing crate `core`?
     span: Span,
     r#type: String,
 }
@@ -805,7 +812,8 @@ struct SuggestionStyleInvalid3 {
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style("foo"))]
 //~^ ERROR expected `= "xxx"`
-//~| ERROr expected `,`
+//~| ERROR failed to resolve: maybe a missing crate `core`?
+//~| NOTE maybe a missing crate `core`?
 struct SuggestionStyleInvalid4 {
     #[primary_span]
     sub: Span,
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 5ddc8edd745..1f267aceb9e 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -38,104 +38,98 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(bug = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: unexpected literal in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:97:9
-   |
-LL | #[label("...")]
-   |         ^^^^^
-
 error: only `no_span` is a valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:106:9
+  --> $DIR/subdiagnostic-derive.rs:107:9
    |
 LL | #[label(slug = 4)]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:106:1
+  --> $DIR/subdiagnostic-derive.rs:107:1
    |
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:116:9
+  --> $DIR/subdiagnostic-derive.rs:117:9
    |
 LL | #[label(slug("..."))]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:116:1
+  --> $DIR/subdiagnostic-derive.rs:117:1
    |
 LL | #[label(slug("..."))]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:136:9
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+  --> $DIR/subdiagnostic-derive.rs:137:1
    |
 LL | #[label()]
-   |         ^
+   | ^^^^^^^^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:145:27
+  --> $DIR/subdiagnostic-derive.rs:146:27
    |
 LL | #[label(no_crate_example, code = "...")]
    |                           ^^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:154:27
+  --> $DIR/subdiagnostic-derive.rs:155:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
    |                           ^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:163:1
+  --> $DIR/subdiagnostic-derive.rs:164:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:177:5
+  --> $DIR/subdiagnostic-derive.rs:178:5
    |
 LL |     #[bar]
    |     ^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:189:5
+  --> $DIR/subdiagnostic-derive.rs:190:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:201:5
+  --> $DIR/subdiagnostic-derive.rs:202:5
    |
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:213:5
+  --> $DIR/subdiagnostic-derive.rs:214:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:225:13
+  --> $DIR/subdiagnostic-derive.rs:226:13
    |
 LL |     #[label(code = "...")]
    |             ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:225:5
+  --> $DIR/subdiagnostic-derive.rs:226:5
    |
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:254:5
+  --> $DIR/subdiagnostic-derive.rs:255:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:251:1
+  --> $DIR/subdiagnostic-derive.rs:252:1
    |
 LL | / #[label(no_crate_example)]
 LL | |
@@ -147,13 +141,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:264:5
+  --> $DIR/subdiagnostic-derive.rs:265:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:274:5
+  --> $DIR/subdiagnostic-derive.rs:275:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -161,97 +155,87 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:285:5
+  --> $DIR/subdiagnostic-derive.rs:286:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:296:5
+  --> $DIR/subdiagnostic-derive.rs:297:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
    |
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
-error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:312:1
-   |
-LL | / union AC {
-LL | |
-LL | |     span: u32,
-LL | |     b: u64,
-LL | | }
-   | |_^
-
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:327:44
+  --> $DIR/subdiagnostic-derive.rs:329:44
    |
 LL | #[label(no_crate_example, no_crate::example)]
    |                                            ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:340:5
+  --> $DIR/subdiagnostic-derive.rs:342:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:337:5
+  --> $DIR/subdiagnostic-derive.rs:339:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:346:8
+  --> $DIR/subdiagnostic-derive.rs:348:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:383:46
+  --> $DIR/subdiagnostic-derive.rs:385:46
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
    |                                              ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:383:32
+  --> $DIR/subdiagnostic-derive.rs:385:32
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
    |                                ^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:401:5
+  --> $DIR/subdiagnostic-derive.rs:403:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:398:5
+  --> $DIR/subdiagnostic-derive.rs:400:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:411:5
+  --> $DIR/subdiagnostic-derive.rs:413:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:424:1
+  --> $DIR/subdiagnostic-derive.rs:426:1
    |
 LL | #[suggestion(no_crate_example)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:434:62
+  --> $DIR/subdiagnostic-derive.rs:436:62
    |
 LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
    |                                                              ^^^^^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:452:1
+  --> $DIR/subdiagnostic-derive.rs:454:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -261,25 +245,25 @@ LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:466:1
+  --> $DIR/subdiagnostic-derive.rs:468:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:486:39
+  --> $DIR/subdiagnostic-derive.rs:488:39
    |
 LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:505:43
+  --> $DIR/subdiagnostic-derive.rs:507:43
    |
 LL |     #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                           ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:528:5
+  --> $DIR/subdiagnostic-derive.rs:530:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
@@ -287,7 +271,7 @@ LL |     #[suggestion_part]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
 
 error: `#[suggestion_part(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:531:5
+  --> $DIR/subdiagnostic-derive.rs:533:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +279,7 @@ LL |     #[suggestion_part(code = "...")]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:525:1
+  --> $DIR/subdiagnostic-derive.rs:527:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -307,7 +291,7 @@ LL | | }
    | |_^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:540:42
+  --> $DIR/subdiagnostic-derive.rs:542:42
    |
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
    |                                          ^^^^
@@ -315,7 +299,7 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac
    = help: only `no_span`, `style` and `applicability` are valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:540:1
+  --> $DIR/subdiagnostic-derive.rs:542:1
    |
 LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 LL | |
@@ -326,19 +310,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:550:5
+  --> $DIR/subdiagnostic-derive.rs:552:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
-error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:558:23
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:560:5
    |
 LL |     #[suggestion_part()]
-   |                       ^
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:567:5
+  --> $DIR/subdiagnostic-derive.rs:569:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -346,7 +330,7 @@ LL |     #[primary_span]
    = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:564:1
+  --> $DIR/subdiagnostic-derive.rs:566:1
    |
 LL | / #[multipart_suggestion(no_crate_example)]
 LL | |
@@ -358,121 +342,91 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:575:5
+  --> $DIR/subdiagnostic-derive.rs:577:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:580:5
+   |
+LL |     #[suggestion_part()]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
 error: `code` is the only valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:581:23
+  --> $DIR/subdiagnostic-derive.rs:583:23
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                       ^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:585:5
+  --> $DIR/subdiagnostic-derive.rs:588:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:588:5
+  --> $DIR/subdiagnostic-derive.rs:591:5
    |
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:578:23
-   |
-LL |     #[suggestion_part()]
-   |                       ^
-
-error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:581:27
-   |
-LL |     #[suggestion_part(foo = "bar")]
-   |                           ^
-
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:596:37
+  --> $DIR/subdiagnostic-derive.rs:599:37
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:596:23
+  --> $DIR/subdiagnostic-derive.rs:599:23
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                       ^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
-  --> $DIR/subdiagnostic-derive.rs:625:5
+  --> $DIR/subdiagnostic-derive.rs:628:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:673:34
+  --> $DIR/subdiagnostic-derive.rs:676:34
    |
 LL |     #[suggestion_part(code("foo"))]
    |                                  ^
 
-error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:673:28
-   |
-LL |     #[suggestion_part(code("foo"))]
-   |                            ^^^^^
-
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:683:41
+  --> $DIR/subdiagnostic-derive.rs:687:41
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
    |                                         ^
 
-error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:683:28
-   |
-LL |     #[suggestion_part(code("foo", "bar"))]
-   |                            ^^^^^
-
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:693:30
+  --> $DIR/subdiagnostic-derive.rs:698:30
    |
 LL |     #[suggestion_part(code(3))]
    |                              ^
 
-error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:693:28
-   |
-LL |     #[suggestion_part(code(3))]
-   |                            ^
-
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:703:29
+  --> $DIR/subdiagnostic-derive.rs:709:29
    |
 LL |     #[suggestion_part(code())]
    |                             ^
 
-error: expected string literal
-  --> $DIR/subdiagnostic-derive.rs:715:30
-   |
-LL |     #[suggestion_part(code = 3)]
-   |                              ^
-
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:757:1
+  --> $DIR/subdiagnostic-derive.rs:764:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:757:1
+  --> $DIR/subdiagnostic-derive.rs:764:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:766:1
+  --> $DIR/subdiagnostic-derive.rs:773:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -480,7 +434,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:774:1
+  --> $DIR/subdiagnostic-derive.rs:781:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -488,7 +442,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: invalid suggestion style
-  --> $DIR/subdiagnostic-derive.rs:782:51
+  --> $DIR/subdiagnostic-derive.rs:789:51
    |
 LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    |                                                   ^^^^^
@@ -496,31 +450,25 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:790:49
+  --> $DIR/subdiagnostic-derive.rs:797:49
    |
 LL | #[suggestion(no_crate_example, code = "", style = 42)]
    |                                                 ^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:798:48
+  --> $DIR/subdiagnostic-derive.rs:805:48
    |
 LL | #[suggestion(no_crate_example, code = "", style)]
    |                                                ^
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:806:48
-   |
-LL | #[suggestion(no_crate_example, code = "", style("foo"))]
-   |                                                ^
-
-error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:806:48
+  --> $DIR/subdiagnostic-derive.rs:813:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
    |                                                ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:818:5
+  --> $DIR/subdiagnostic-derive.rs:826:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -529,7 +477,7 @@ LL |     #[primary_span]
    = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:815:1
+  --> $DIR/subdiagnostic-derive.rs:823:1
    |
 LL | / #[suggestion(no_crate_example, code = "")]
 LL | |
@@ -540,6 +488,54 @@ LL | |     sub: Vec<Span>,
 LL | | }
    | |_^
 
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:97:9
+   |
+LL | #[label("...")]
+   |         ^^^^^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:313:1
+   |
+LL | union AC {
+   | ^^^^^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:583:27
+   |
+LL |     #[suggestion_part(foo = "bar")]
+   |                           ^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:676:28
+   |
+LL |     #[suggestion_part(code("foo"))]
+   |                            ^^^^^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:687:28
+   |
+LL |     #[suggestion_part(code("foo", "bar"))]
+   |                            ^^^^^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:698:28
+   |
+LL |     #[suggestion_part(code(3))]
+   |                            ^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:721:30
+   |
+LL |     #[suggestion_part(code = 3)]
+   |                              ^ maybe a missing crate `core`?
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/subdiagnostic-derive.rs:813:48
+   |
+LL | #[suggestion(no_crate_example, code = "", style("foo"))]
+   |                                                ^ maybe a missing crate `core`?
+
 error: cannot find attribute `foo` in this scope
   --> $DIR/subdiagnostic-derive.rs:68:3
    |
@@ -547,61 +543,61 @@ LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:163:3
+  --> $DIR/subdiagnostic-derive.rs:164:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:177:7
+  --> $DIR/subdiagnostic-derive.rs:178:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:189:7
+  --> $DIR/subdiagnostic-derive.rs:190:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:201:7
+  --> $DIR/subdiagnostic-derive.rs:202:7
    |
 LL |     #[bar = 4]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:213:7
+  --> $DIR/subdiagnostic-derive.rs:214:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:274:7
+  --> $DIR/subdiagnostic-derive.rs:275:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:285:7
+  --> $DIR/subdiagnostic-derive.rs:286:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:296:7
+  --> $DIR/subdiagnostic-derive.rs:297:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
-  --> $DIR/subdiagnostic-derive.rs:126:9
+  --> $DIR/subdiagnostic-derive.rs:127:9
    |
 LL | #[label(slug)]
    |         ^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_29` in this scope
-  --> $DIR/subdiagnostic-derive.rs:709:10
+  --> $DIR/subdiagnostic-derive.rs:715:10
    |
 LL | #[derive(Subdiagnostic)]
    |          ^^^^^^^^^^^^^ not found in this scope
@@ -610,4 +606,5 @@ LL | #[derive(Subdiagnostic)]
 
 error: aborting due to 86 previous errors
 
-For more information about this error, try `rustc --explain E0425`.
+Some errors have detailed explanations: E0425, E0433.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/impl-trait/autoderef.rs b/tests/ui/impl-trait/autoderef.rs
index 0d07a549640..cd2cdd9e3b3 100644
--- a/tests/ui/impl-trait/autoderef.rs
+++ b/tests/ui/impl-trait/autoderef.rs
@@ -1,5 +1,5 @@
 // revisions: current next
-//[next] compile-flag: -Ztrait-solver=next
+//[next] compile-flags: -Ztrait-solver=next
 // check-pass
 
 use std::path::Path;
diff --git a/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs b/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs
new file mode 100644
index 00000000000..b241e3bf865
--- /dev/null
+++ b/tests/ui/traits/new-solver/dont-loop-fulfill-on-region-constraints.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+trait Eq<'a, 'b, T> {}
+
+trait Ambig {}
+impl Ambig for () {}
+
+impl<'a, T> Eq<'a, 'a, T> for () where T: Ambig {}
+
+fn eq<'a, 'b, T>(t: T)
+where
+    (): Eq<'a, 'b, T>,
+{
+}
+
+fn test<'r>() {
+    let mut x = Default::default();
+
+    // When we evaluate `(): Eq<'r, 'r, ?0>` we uniquify the regions.
+    // That leads us to evaluate `(): Eq<'?0, '?1, ?0>`. The response of this
+    // will be ambiguous (because `?0: Ambig` is ambig) and also not an "identity"
+    // response, since the region constraints will contain `'?0 == '?1` (so
+    // `is_changed` will return true). Since it's both ambig and changed,
+    // fulfillment will both re-register the goal AND loop again. This hits the
+    // overflow limit. This should neither be considered overflow, nor ICE.
+    eq::<'r, 'r, _>(x);
+
+    x = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/broken_mir.rs b/tests/ui/type-alias-impl-trait/broken_mir.rs
new file mode 100644
index 00000000000..b68e798fb7c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/broken_mir.rs
@@ -0,0 +1,16 @@
+//! ICE: https://github.com/rust-lang/rust/issues/114121
+//! This test checks that MIR validation never constrains
+//! new hidden types that *differ* from the actual hidden types.
+//! This test used to ICE because oli-obk assumed mir validation
+//! was only ever run after opaque types were revealed in MIR.
+
+// compile-flags: -Zvalidate-mir
+// check-pass
+
+fn main() {
+    let _ = Some(()).into_iter().flat_map(|_| Some(()).into_iter().flat_map(func));
+}
+
+fn func(_: ()) -> impl Iterator<Item = ()> {
+    Some(()).into_iter().flat_map(|_| vec![])
+}