Auto merge of #70832 - Centril:rollup-ixc09ve, r=Centril

Rollup of 5 pull requests

Successful merges:

 - #70519 (Tweak output of type params and constraints in the wrong order)
 - #70704 (Make panic unwind the default for aarch64-*-windows-msvc targets)
 - #70713 (Prefer sysroot from rustc in same directory as rust-gdb)
 - #70739 (def_collector, visit_fn: account for no body)
 - #70827 (Use smaller span for suggestion restricting lifetime)

Failed merges:

r? @ghost
diff --git a/Cargo.lock b/Cargo.lock
index 28dcd30..908bfa3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3564,6 +3564,7 @@
 name = "rustc_ast_passes"
 version = "0.0.0"
 dependencies = [
+ "itertools 0.8.0",
  "log",
  "rustc_ast",
  "rustc_ast_pretty",
diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb
index 23ba93d..b950cea 100755
--- a/src/etc/rust-gdb
+++ b/src/etc/rust-gdb
@@ -2,8 +2,16 @@
 # Exit if anything fails
 set -e
 
+# Prefer rustc in the same directory as this script
+DIR="$(dirname "$0")"
+if [ -x "$DIR/rustc" ]; then
+  RUSTC="$DIR/rustc"
+else
+  RUSTC="rustc"
+fi
+
 # Find out where the pretty printer Python module is
-RUSTC_SYSROOT=`rustc --print=sysroot`
+RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)"
 GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
 
 # Run GDB with the additional arguments that load the pretty printers
diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui
index 08d598c..9744913 100755
--- a/src/etc/rust-gdbgui
+++ b/src/etc/rust-gdbgui
@@ -31,8 +31,16 @@
     exit 0
 fi
 
+# Prefer rustc in the same directory as this script
+DIR="$(dirname "$0")"
+if [ -x "$DIR/rustc" ]; then
+  RUSTC="$DIR/rustc"
+else
+  RUSTC="rustc"
+fi
+
 # Find out where the pretty printer Python module is
-RUSTC_SYSROOT=`rustc --print=sysroot`
+RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)"
 GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
 
 # Set the environment variable `RUST_GDB` to overwrite the call to a
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 0a2a0e9..f791fe8 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -47,9 +47,6 @@
     } else if #[cfg(target_os = "hermit")] {
         #[path = "hermit.rs"]
         mod real_imp;
-    } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
-        #[path = "dummy.rs"]
-        mod real_imp;
     } else if #[cfg(target_env = "msvc")] {
         #[path = "seh.rs"]
         mod real_imp;
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index 10b765a..9eff37f 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -117,7 +117,7 @@
     }
 }
 
-#[cfg(any(target_arch = "x86_64", target_arch = "arm"))]
+#[cfg(not(target_arch = "x86"))]
 #[macro_use]
 mod imp {
     pub type ptr_t = u32;
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 6586280..f91cbe5 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -300,8 +300,8 @@
 impl GenericBound {
     pub fn span(&self) -> Span {
         match self {
-            &GenericBound::Trait(ref t, ..) => t.span,
-            &GenericBound::Outlives(ref l) => l.ident.span,
+            GenericBound::Trait(ref t, ..) => t.span,
+            GenericBound::Outlives(ref l) => l.ident.span,
         }
     }
 }
diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml
index 5d096e4..e4d1d79 100644
--- a/src/librustc_ast_passes/Cargo.toml
+++ b/src/librustc_ast_passes/Cargo.toml
@@ -9,6 +9,7 @@
 path = "lib.rs"
 
 [dependencies]
+itertools = "0.8"
 log = "0.4"
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index de7ae10..9563325f 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -6,6 +6,7 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
+use itertools::{Either, Itertools};
 use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::expand::is_proc_macro_attr;
@@ -14,7 +15,7 @@
 use rustc_ast::walk_list;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, struct_span_err, Applicability};
+use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
 use rustc_session::lint::LintBuffer;
@@ -640,6 +641,33 @@
         }
     }
 
+    fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
+        // Lifetimes always come first.
+        let lt_sugg = data.args.iter().filter_map(|arg| match arg {
+            AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
+                Some(pprust::to_string(|s| s.print_generic_arg(lt)))
+            }
+            _ => None,
+        });
+        let args_sugg = data.args.iter().filter_map(|a| match a {
+            AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
+                None
+            }
+            AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
+        });
+        // Constraints always come last.
+        let constraint_sugg = data.args.iter().filter_map(|a| match a {
+            AngleBracketedArg::Arg(_) => None,
+            AngleBracketedArg::Constraint(c) => {
+                Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
+            }
+        });
+        format!(
+            "<{}>",
+            lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
+        )
+    }
+
     /// Enforce generic args coming before constraints in `<...>` of a path segment.
     fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
         // Early exit in case it's partitioned as it should be.
@@ -647,24 +675,36 @@
             return;
         }
         // Find all generic argument coming after the first constraint...
-        let mut misplaced_args = Vec::new();
-        let mut first = None;
-        for arg in &data.args {
-            match (arg, first) {
-                (AngleBracketedArg::Arg(a), Some(_)) => misplaced_args.push(a.span()),
-                (AngleBracketedArg::Constraint(c), None) => first = Some(c.span),
-                (AngleBracketedArg::Arg(_), None) | (AngleBracketedArg::Constraint(_), Some(_)) => {
-                }
-            }
-        }
+        let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
+            data.args.iter().partition_map(|arg| match arg {
+                AngleBracketedArg::Constraint(c) => Either::Left(c.span),
+                AngleBracketedArg::Arg(a) => Either::Right(a.span()),
+            });
+        let args_len = arg_spans.len();
+        let constraint_len = constraint_spans.len();
         // ...and then error:
         self.err_handler()
             .struct_span_err(
-                misplaced_args.clone(),
+                arg_spans.clone(),
                 "generic arguments must come before the first constraint",
             )
-            .span_label(first.unwrap(), "the first constraint is provided here")
-            .span_labels(misplaced_args, "generic argument")
+            .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
+            .span_label(
+                *arg_spans.iter().last().unwrap(),
+                &format!("generic argument{}", pluralize!(args_len)),
+            )
+            .span_labels(constraint_spans, "")
+            .span_labels(arg_spans, "")
+            .span_suggestion_verbose(
+                data.span,
+                &format!(
+                    "move the constraint{} after the generic argument{}",
+                    pluralize!(constraint_len),
+                    pluralize!(args_len)
+                ),
+                self.correct_generic_order_suggestion(&data),
+                Applicability::MachineApplicable,
+            )
             .emit();
     }
 }
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 6541ac1..f688686 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -869,7 +869,7 @@
         }
     }
 
-    fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
+    pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
         self.print_ident(constraint.ident);
         self.s.space();
         match &constraint.kind {
@@ -883,7 +883,7 @@
         }
     }
 
-    crate fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
+    pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
         match generic_arg {
             GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
             GenericArg::Type(ty) => self.print_type(ty),
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index fffae0b..2dbd9f4 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -315,6 +315,20 @@
         self
     }
 
+    pub fn span_suggestion_verbose(
+        &mut self,
+        sp: Span,
+        msg: &str,
+        suggestion: String,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.0.allow_suggestions {
+            return self;
+        }
+        self.0.diagnostic.span_suggestion_verbose(sp, msg, suggestion, applicability);
+        self
+    }
+
     pub fn span_suggestion_hidden(
         &mut self,
         sp: Span,
diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 7340e88..7645182 100644
--- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -208,45 +208,34 @@
                     );
                 };
 
-                self.add_lifetime_bound_suggestion_to_diagnostic(
-                    tcx,
-                    err,
-                    &category,
-                    span,
-                    region_name,
-                );
+                self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
             }
             _ => {}
         }
     }
-    pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic<'tcx>(
+    pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic(
         &self,
-        tcx: TyCtxt<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         category: &ConstraintCategory,
         span: Span,
         region_name: &RegionName,
     ) {
         if let ConstraintCategory::OpaqueType = category {
-            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
-                let suggestable_name = if region_name.was_named() {
-                    region_name.to_string()
-                } else {
-                    "'_".to_string()
-                };
+            let suggestable_name =
+                if region_name.was_named() { region_name.to_string() } else { "'_".to_string() };
 
-                err.span_suggestion(
-                    span,
-                    &format!(
-                        "you can add a bound to the {}to make it last less than \
-                             `'static` and match `{}`",
-                        category.description(),
-                        region_name,
-                    ),
-                    format!("{} + {}", snippet, suggestable_name),
-                    Applicability::Unspecified,
-                );
-            }
+            let msg = format!(
+                "you can add a bound to the {}to make it last less than `'static` and match `{}`",
+                category.description(),
+                region_name,
+            );
+
+            err.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                &msg,
+                format!(" + {}", suggestable_name),
+                Applicability::Unspecified,
+            );
         }
     }
 }
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 6253f18..71cedb2 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -2,6 +2,7 @@
 use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
 use rustc_ast::visit::{self, FnKind};
+use rustc_ast::walk_list;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::definitions::*;
@@ -117,10 +118,8 @@
                 // we must mirror everything that `visit::walk_fn` below does.
                 self.visit_fn_header(&sig.header);
                 visit::walk_fn_decl(self, &sig.decl);
-                if let Some(body) = body {
-                    let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
-                    self.with_parent(closure_def, |this| this.visit_block(body));
-                }
+                let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
+                self.with_parent(closure_def, |this| walk_list!(this, visit_block, body));
                 return;
             }
         }
diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs
index 7a46c7d..8c03f1e 100644
--- a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
@@ -6,9 +6,6 @@
     base.has_elf_tls = true;
     base.features = "+neon,+fp-armv8".to_string();
 
-    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
-    base.panic_strategy = PanicStrategy::Abort;
-
     Ok(Target {
         llvm_target: "aarch64-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs
index a793860..6a8d148 100644
--- a/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs
+++ b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs
@@ -1,13 +1,10 @@
-use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_uwp_msvc_base::opts();
     base.max_atomic_width = Some(64);
     base.has_elf_tls = true;
 
-    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
-    base.panic_strategy = PanicStrategy::Abort;
-
     Ok(Target {
         llvm_target: "aarch64-pc-windows-msvc".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/llvm-project b/src/llvm-project
index 130721d..027e428 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 130721d6f4e6cba3b910ccdf5e0aa62b9dffc95f
+Subproject commit 027e428197f3702599cfbb632883768175f49173
diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.stderr b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
index 83d0f87..9cff4bc 100644
--- a/src/test/ui/impl-trait/does-not-live-long-enough.stderr
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
@@ -14,7 +14,7 @@
 help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
    |
 LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> + 'a {
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                                                   ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr
index 742f4fd..bc61b3b 100644
--- a/src/test/ui/parser/issue-32214.stderr
+++ b/src/test/ui/parser/issue-32214.stderr
@@ -4,7 +4,12 @@
 LL | pub fn test<W, I: Trait<Item=(), W> >() {}
    |                         -------  ^ generic argument
    |                         |
-   |                         the first constraint is provided here
+   |                         constraint
+   |
+help: move the constraint after the generic argument
+   |
+LL | pub fn test<W, I: Trait<W, Item = ()> >() {}
+   |                        ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
new file mode 100644
index 0000000..cc36f05
--- /dev/null
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
@@ -0,0 +1,20 @@
+// edition:2018
+
+async fn free(); //~ ERROR without a body
+
+struct A;
+impl A {
+    async fn inherent(); //~ ERROR without body
+}
+
+trait B {
+    async fn associated();
+    //~^ ERROR cannot be declared `async`
+}
+impl B for A {
+    async fn associated(); //~ ERROR without body
+    //~^ ERROR cannot be declared `async`
+    //~| ERROR incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
new file mode 100644
index 0000000..a324d04
--- /dev/null
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
@@ -0,0 +1,65 @@
+error: free function without a body
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:3:1
+   |
+LL | async fn free();
+   | ^^^^^^^^^^^^^^^-
+   |                |
+   |                help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:7:5
+   |
+LL |     async fn inherent();
+   |     ^^^^^^^^^^^^^^^^^^^-
+   |                        |
+   |                        help: provide a definition for the function: `{ <body> }`
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5
+   |
+LL |     async fn associated();
+   |     -----^^^^^^^^^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error: associated function in `impl` without body
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
+   |
+LL |     async fn associated();
+   |     ^^^^^^^^^^^^^^^^^^^^^-
+   |                          |
+   |                          help: provide a definition for the function: `{ <body> }`
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
+   |
+LL |     async fn associated();
+   |     -----^^^^^^^^^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error[E0053]: method `associated` has an incompatible type for trait
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
+   |
+LL |     async fn associated();
+   |                          - type in trait
+...
+LL |     async fn associated();
+   |                          ^
+   |                          |
+   |                          the `Output` of this `async fn`'s found opaque type
+   |                          expected `()`, found opaque type
+   |
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn() -> impl std::future::Future`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0053, E0706.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr
index 4dd0613..3bb6fd6 100644
--- a/src/test/ui/suggestions/suggest-move-types.stderr
+++ b/src/test/ui/suggestions/suggest-move-types.stderr
@@ -4,79 +4,103 @@
 LL | struct A<T, M: One<A=(), T>> {
    |                    ----  ^ generic argument
    |                    |
-   |                    the first constraint is provided here
+   |                    constraint
+   |
+help: move the constraint after the generic argument
+   |
+LL | struct A<T, M: One<T, A = ()>> {
+   |                   ^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
   --> $DIR/suggest-move-types.rs:33:43
    |
 LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
-   |                                     ----  ^  ^^ generic argument
-   |                                     |     |
-   |                                     |     generic argument
-   |                                     the first constraint is provided here
+   |                                     ----  ^  ^^ generic arguments
+   |                                     |
+   |                                     constraint
+   |
+help: move the constraint after the generic arguments
+   |
+LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A = ()>> {
+   |                                    ^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
   --> $DIR/suggest-move-types.rs:40:46
    |
 LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
-   |                            ----              ^  ^  ^ generic argument
-   |                            |                 |  |
-   |                            |                 |  generic argument
-   |                            |                 generic argument
-   |                            the first constraint is provided here
+   |                            ----  ----  ----  ^  ^  ^ generic arguments
+   |                            |
+   |                            constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct B<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
   --> $DIR/suggest-move-types.rs:48:71
    |
 LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
-   |                                                     ----              ^  ^  ^  ^^  ^^  ^^ generic argument
-   |                                                     |                 |  |  |  |   |
-   |                                                     |                 |  |  |  |   generic argument
-   |                                                     |                 |  |  |  generic argument
-   |                                                     |                 |  |  generic argument
-   |                                                     |                 |  generic argument
-   |                                                     |                 generic argument
-   |                                                     the first constraint is provided here
+   |                                                     ----  ----  ----  ^  ^  ^  ^^  ^^  ^^ generic arguments
+   |                                                     |
+   |                                                     constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
-  --> $DIR/suggest-move-types.rs:57:49
+  --> $DIR/suggest-move-types.rs:57:28
    |
 LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
-   |                               ----              ^  ^ generic argument
-   |                               |                 |
-   |                               |                 generic argument
-   |                               the first constraint is provided here
+   |                            ^  ----  ----  ----  ^  ^ generic arguments
+   |                               |
+   |                               constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct C<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
-  --> $DIR/suggest-move-types.rs:65:78
+  --> $DIR/suggest-move-types.rs:65:53
    |
 LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
-   |                                                            ----              ^  ^^  ^  ^^ generic argument
-   |                                                            |                 |  |   |
-   |                                                            |                 |  |   generic argument
-   |                                                            |                 |  generic argument
-   |                                                            |                 generic argument
-   |                                                            the first constraint is provided here
+   |                                                     ^  ^^  ----  ----  ----  ^  ^^  ^  ^^ generic arguments
+   |                                                            |
+   |                                                            constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
-  --> $DIR/suggest-move-types.rs:74:43
+  --> $DIR/suggest-move-types.rs:74:28
    |
 LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
-   |                               ----        ^        ^ generic argument
-   |                               |           |
-   |                               |           generic argument
-   |                               the first constraint is provided here
+   |                            ^  ----  ----  ^  ----  ^ generic arguments
+   |                               |
+   |                               constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct D<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: generic arguments must come before the first constraint
-  --> $DIR/suggest-move-types.rs:82:72
+  --> $DIR/suggest-move-types.rs:82:53
    |
 LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
-   |                                                            ----        ^  ^^        ^  ^^ generic argument
-   |                                                            |           |  |         |
-   |                                                            |           |  |         generic argument
-   |                                                            |           |  generic argument
-   |                                                            |           generic argument
-   |                                                            the first constraint is provided here
+   |                                                     ^  ^^  ----  ----  ^  ^^  ----  ^  ^^ generic arguments
+   |                                                            |
+   |                                                            constraints
+   |
+help: move the constraints after the generic arguments
+   |
+LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0747]: type provided when a lifetime was expected
   --> $DIR/suggest-move-types.rs:33:43