about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs7
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl9
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs55
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs24
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs10
-rw-r--r--library/core/src/ffi/c_str.rs17
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--tests/ui/error-codes/E0637.stderr7
-rw-r--r--tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr7
-rw-r--r--tests/ui/impl-trait/in-trait/foreign.rs4
-rw-r--r--tests/ui/impl-trait/in-trait/variances-of-gat.rs19
-rw-r--r--tests/ui/impl-trait/universal_wrong_hrtb.rs2
-rw-r--r--tests/ui/impl-trait/universal_wrong_hrtb.stderr10
-rw-r--r--tests/ui/suggestions/suggest-split-at-mut.stderr1
-rw-r--r--tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr17
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed17
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs17
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr (renamed from tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr (renamed from tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed14
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs14
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr (renamed from tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed15
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs15
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr (renamed from tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs15
32 files changed, 327 insertions, 99 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index a068f2d6926..33b07aae325 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -982,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &msg_borrow,
                     None,
                 );
-                self.suggest_split_at_mut_if_applicable(
+                self.suggest_slice_method_if_applicable(
                     &mut err,
                     place,
                     issued_borrow.borrowed_place,
@@ -1262,7 +1262,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         );
     }
 
-    fn suggest_split_at_mut_if_applicable(
+    fn suggest_slice_method_if_applicable(
         &self,
         err: &mut Diagnostic,
         place: Place<'tcx>,
@@ -1274,7 +1274,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.help(
                 "consider using `.split_at_mut(position)` or similar method to obtain \
                      two mutable non-overlapping sub-slices",
-            );
+            )
+            .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index edc6bcacc68..ad26c495c02 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
 hir_analysis_invalid_union_field_sugg =
     wrap the field type in `ManuallyDrop<...>`
 
+hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
+    .label = const parameter declared here
+
+hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
+    .label = lifetime declared here
+
+hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
+    .label = type parameter declared here
+
 hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
     .label = lifetimes do not match {$item_kind} in trait
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index c8b405228a5..97a3e01c52a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Binder {
                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
                 } => {
-                    let mut err = self.tcx.sess.struct_span_err(
-                        lifetime_ref.ident.span,
-                        "`impl Trait` can only mention lifetimes bound at the fn or impl level",
-                    );
-                    err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
-                    err.emit();
+                    self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
+                        span: lifetime_ref.ident.span,
+                        param_span: self.tcx.def_span(region_def_id),
+                    });
                     return;
                 }
                 Scope::Root { .. } => break,
@@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let mut late_depth = 0;
         let mut scope = self.scope;
         let mut crossed_anon_const = false;
+
         let result = loop {
             match *scope {
                 Scope::Body { s, .. } => {
@@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             return;
         }
 
+        // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
+        // AST-based resolution does not care for impl-trait desugaring, which are the
+        // responsibility of lowering. This may create a mismatch between the resolution
+        // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
+        // ```
+        // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
+        // ```
+        //
+        // In such case, walk back the binders to diagnose it properly.
+        let mut scope = self.scope;
+        loop {
+            match *scope {
+                Scope::Binder {
+                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
+                } => {
+                    let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
+                        DefKind::TyParam => errors::LateBoundInApit::Type {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        DefKind::ConstParam => errors::LateBoundInApit::Const {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        kind => {
+                            bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
+                        }
+                    });
+                    self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+                    return;
+                }
+                Scope::Root { .. } => break,
+                Scope::Binder { s, .. }
+                | Scope::Body { s, .. }
+                | Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
+                    scope = s;
+                }
+            }
+        }
+
         self.tcx.sess.delay_span_bug(
             self.tcx.hir().span(hir_id),
             format!("could not resolve {param_def_id:?}"),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7dce1272f96..cb840592edd 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
         param_span: Span,
     },
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum LateBoundInApit {
+    #[diag(hir_analysis_late_bound_type_in_apit)]
+    Type {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_const_in_apit)]
+    Const {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_lifetime_in_apit)]
+    Lifetime {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 23d8da88a45..49aee6b59a2 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
 
@@ -51,20 +51,26 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
         | DefKind::Struct
         | DefKind::Union
         | DefKind::Variant
-        | DefKind::Ctor(..) => {}
+        | DefKind::Ctor(..) => {
+            // These are inferred.
+            let crate_map = tcx.crate_variances(());
+            return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
+        }
         DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
             return variance_of_opaque(tcx, item_def_id);
         }
-        _ => {
-            // Variance not relevant.
-            span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item")
+        DefKind::AssocTy => {
+            if let Some(ImplTraitInTraitData::Trait { .. }) =
+                tcx.opt_rpitit_info(item_def_id.to_def_id())
+            {
+                return variance_of_opaque(tcx, item_def_id);
+            }
         }
+        _ => {}
     }
 
-    // Everything else must be inferred.
-
-    let crate_map = tcx.crate_variances(());
-    crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
+    // Variance not relevant.
+    span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
 }
 
 #[instrument(level = "trace", skip(tcx), ret)]
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b80019bf155..efe49d687c9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1447,6 +1447,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     .is_type_alias_impl_trait
                     .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
             }
+            if let DefKind::ImplTraitPlaceholder = def_kind {
+                self.encode_explicit_item_bounds(def_id);
+            }
             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
             {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9f4573ea025..744dcf0db84 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1632,9 +1632,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                 ..
                             } = &rib.kind
                             {
-                                diag.span_help(
-                                    *span,
-                                    "consider introducing a higher-ranked lifetime here with `for<'a>`",
+                                diag.multipart_suggestion(
+                                    "consider introducing a higher-ranked lifetime here",
+                                    vec![
+                                        (span.shrink_to_lo(), "for<'a> ".into()),
+                                        (lifetime.ident.span.shrink_to_hi(), "'a ".into()),
+                                    ],
+                                    Applicability::MachineApplicable,
                                 );
                                 break;
                             }
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 50c7516b7fe..3de9188baf6 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -241,7 +241,7 @@ impl CStr {
     /// ```
     ///
     /// ```
-    /// #![feature(const_cstr_methods)]
+    /// #![feature(const_cstr_from_ptr)]
     ///
     /// use std::ffi::{c_char, CStr};
     ///
@@ -256,7 +256,7 @@ impl CStr {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
     pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
         // SAFETY: The caller has provided a pointer that points to a valid C
         // string with a NUL terminator of size less than `isize::MAX`, whose
@@ -377,7 +377,7 @@ impl CStr {
     /// assert!(cstr.is_err());
     /// ```
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
     pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
         let nul_pos = memchr::memchr(0, bytes);
         match nul_pos {
@@ -561,10 +561,12 @@ impl CStr {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_bytes(&self) -> &[u8] {
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn to_bytes(&self) -> &[u8] {
         let bytes = self.to_bytes_with_nul();
+        // FIXME(const-hack) replace with range index
         // SAFETY: to_bytes_with_nul returns slice with length at least 1
-        unsafe { bytes.get_unchecked(..bytes.len() - 1) }
+        unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
     }
 
     /// Converts this C string to a byte slice containing the trailing 0 byte.
@@ -588,7 +590,7 @@ impl CStr {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
     pub const fn to_bytes_with_nul(&self) -> &[u8] {
         // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
         // is safe on all supported targets.
@@ -612,7 +614,8 @@ impl CStr {
     /// assert_eq!(cstr.to_str(), Ok("foo"));
     /// ```
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
-    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
         // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
         // instead of in `from_ptr()`, it may be worth considering if this should
         // be rewritten to do the UTF-8 check inline with the length calculation
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 6c419eb16f3..05876f5fc58 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -113,7 +113,6 @@
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_char_from_u32_unchecked)]
-#![feature(const_cstr_methods)]
 #![feature(const_discriminant)]
 #![feature(const_eval_select)]
 #![feature(const_exact_div)]
diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr
index 78341735e19..d9db89ddb0c 100644
--- a/tests/ui/error-codes/E0637.stderr
+++ b/tests/ui/error-codes/E0637.stderr
@@ -22,11 +22,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
 LL |     T: Into<&u32>,
    |             ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/E0637.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: Into<&u32>,
-   |        ^
+LL |     T: for<'a> Into<&'a u32>,
+   |        +++++++       ++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index faf4c9eb872..bcd1fbc55ed 100644
--- a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -4,11 +4,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
 LL | fn should_error<T>() where T : Into<&u32> {}
    |                                     ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32
+help: consider introducing a higher-ranked lifetime here
    |
-LL | fn should_error<T>() where T : Into<&u32> {}
-   |                                ^
+LL | fn should_error<T>() where T : for<'a> Into<&'a u32> {}
+   |                                +++++++       ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20
diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs
index 98417b343a1..b0fbe3a3d4a 100644
--- a/tests/ui/impl-trait/in-trait/foreign.rs
+++ b/tests/ui/impl-trait/in-trait/foreign.rs
@@ -14,6 +14,10 @@ impl Foo for Local {
     fn bar(self) -> Arc<String> { Arc::new(String::new()) }
 }
 
+fn generic(f: impl Foo) {
+    let x = &*f.bar();
+}
+
 fn main() {
     // Witness an RPITIT from another crate.
     let &() = Foreign.bar();
diff --git a/tests/ui/impl-trait/in-trait/variances-of-gat.rs b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
new file mode 100644
index 00000000000..4008ece94da
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
@@ -0,0 +1,19 @@
+// check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
+#![feature(return_position_impl_trait_in_trait)]
+
+trait Foo {}
+
+impl Foo for () {}
+
+trait ThreeCellFragment {
+    fn ext_cells<'a>(&'a self) -> impl Foo + 'a {
+        self.ext_adjacent_cells()
+    }
+
+    fn ext_adjacent_cells<'a>(&'a self) -> impl Foo + 'a;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.rs b/tests/ui/impl-trait/universal_wrong_hrtb.rs
index b9551c2ceb0..48561710143 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.rs
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.rs
@@ -3,6 +3,6 @@ trait Trait<'a> {
 }
 
 fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
+//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl
 
 fn main() {}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.stderr b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
index 37eb8dfa1a1..b5a091b61fa 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.stderr
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
@@ -1,14 +1,8 @@
-error: `impl Trait` can only mention lifetimes bound at the fn or impl level
+error: `impl Trait` can only mention lifetimes from an fn or impl
   --> $DIR/universal_wrong_hrtb.rs:5:73
    |
 LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                                                         ^^
-   |
-note: lifetime declared here
-  --> $DIR/universal_wrong_hrtb.rs:5:39
-   |
-LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                       ^^
+   |                                       -- lifetime declared here         ^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr
index 330f012b2a9..bb185138383 100644
--- a/tests/ui/suggestions/suggest-split-at-mut.stderr
+++ b/tests/ui/suggestions/suggest-split-at-mut.stderr
@@ -9,6 +9,7 @@ LL |     *a = 5;
    |     ------ first borrow later used here
    |
    = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
+   = help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
new file mode 100644
index 00000000000..e9ae00df7a0
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait<Input> {
+    type Assoc;
+}
+
+fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
new file mode 100644
index 00000000000..1124076c23c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` can only mention type parameters from an fn or impl
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52
+   |
+LL | fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+   |                    - type parameter declared here  ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed
new file mode 100644
index 00000000000..5be6ff8e7e1
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs
new file mode 100644
index 00000000000..d7072aa1181
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr
index 63fc1a19b93..3e197dc9a9d 100644
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-trait-impl-region.rs:11:17
+  --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:13:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-trait-impl-region.rs:11:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed
new file mode 100644
index 00000000000..0f1be586589
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs
new file mode 100644
index 00000000000..59f7e472e2d
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr
index 63fc1a19b93..08b4268e5d2 100644
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-trait-impl-region.rs:11:17
+  --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:14:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-trait-impl-region.rs:11:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
deleted file mode 100644
index 43de30944ca..00000000000
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: rust2015 rust2018
-//[rust2018] edition:2018
-
-trait WithType<T> {}
-trait WithRegion<'a> { }
-
-struct Foo<T> {
-    t: T
-}
-
-impl<T> Foo<T>
-where
-    T: WithType<&u32>
-//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
-{ }
-
-fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed
new file mode 100644
index 00000000000..55c7470960e
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs
new file mode 100644
index 00000000000..42a35b02161
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr
index f4d14b5f87b..8c5bbb631b4 100644
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+  --> $DIR/where-clause-trait-impl-region-2015.rs:10:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed
new file mode 100644
index 00000000000..09b96fe5ea4
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+// edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs
new file mode 100644
index 00000000000..445f38cbee1
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+// edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr
index f4d14b5f87b..0268c59fa4a 100644
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+  --> $DIR/where-clause-trait-impl-region-2018.rs:11:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs
deleted file mode 100644
index 09e5bbd846d..00000000000
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// revisions: rust2015 rust2018
-//[rust2018] edition:2018
-
-trait WithType<T> {}
-trait WithRegion<'a> { }
-
-trait Foo { }
-
-impl<T> Foo for Vec<T>
-where
-    T: WithType<&u32>
-//[rust2015,rust2018]~^ ERROR `&` without an explicit lifetime name cannot be used here
-{ }
-
-fn main() {}