diff --git a/Cargo.lock b/Cargo.lock index 28dcd3026fc..908bfa35557 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3564,6 +3564,7 @@ dependencies = [ 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 23ba93da8e5..b950cea79ed 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 08d598cde1c..9744913b686 100755 --- a/src/etc/rust-gdbgui +++ b/src/etc/rust-gdbgui @@ -31,8 +31,16 @@ icon to start your program running. 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 0a2a0e9e045..f791fe82a27 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -47,9 +47,6 @@ cfg_if::cfg_if! { } 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 10b765a5b41..9eff37f1766 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -117,7 +117,7 @@ mod imp { } } -#[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 6586280d214..f91cbe51d85 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -300,8 +300,8 @@ pub enum GenericBound { 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 5d096e4965d..e4d1d79abb2 100644 --- a/src/librustc_ast_passes/Cargo.toml +++ b/src/librustc_ast_passes/Cargo.toml @@ -9,6 +9,7 @@ name = "rustc_ast_passes" 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 de7ae10723f..9563325fe32 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::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; 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 @@ impl<'a> AstValidator<'a> { } } + 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::>().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 @@ impl<'a> AstValidator<'a> { 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, Vec) = + 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 6541ac156b4..f68868633f1 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -869,7 +869,7 @@ impl<'a> State<'a> { } } - 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 @@ impl<'a> State<'a> { } } - 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 fffae0bfd24..2dbd9f4e52f 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -315,6 +315,20 @@ impl<'a> DiagnosticBuilder<'a> { 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 7340e88f19b..7645182ad1f 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 @@ impl BorrowExplanation { ); }; - 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 6253f183cc4..71cedb208fc 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -2,6 +2,7 @@ use log::debug; 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 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // 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 7a46c7da7c3..8c03f1e8a7e 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 @@ pub fn target() -> TargetResult { 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 a793860260c..6a8d148259a 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 130721d6f4e..027e428197f 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 83d0f87015b..9cff4bcd8b5 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 @@ LL | } 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 + '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 742f4fdc38b..bc61b3b74e2 100644 --- a/src/test/ui/parser/issue-32214.stderr +++ b/src/test/ui/parser/issue-32214.stderr @@ -4,7 +4,12 @@ error: generic arguments must come before the first constraint LL | pub fn test >() {} | ------- ^ generic argument | | - | the first constraint is provided here + | constraint + | +help: move the constraint after the generic argument + | +LL | pub fn test >() {} + | ^^^^^^^^^^^^^^ 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 00000000000..cc36f054bc3 --- /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 00000000000..a324d04d394 --- /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: `{ }` + +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: `{ }` + +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: `{ }` + +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 4dd0613757a..3bb6fd6e4f4 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -4,79 +4,103 @@ error: generic arguments must come before the first constraint LL | struct A> { | ---- ^ generic argument | | - | the first constraint is provided here + | constraint + | +help: move the constraint after the generic argument + | +LL | struct A> { + | ^^^^^^^^^^^ error: generic arguments must come before the first constraint --> $DIR/suggest-move-types.rs:33:43 | LL | struct Al<'a, T, M: OneWithLifetime> { - | ---- ^ ^^ 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> { - | ---- ^ ^ ^ 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> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> { - | ---- ^ ^ ^ ^^ ^^ ^^ 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> { - | ---- ^ ^ generic argument - | | | - | | generic argument - | the first constraint is provided here + | ^ ---- ---- ---- ^ ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct 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> { - | ---- ^ ^^ ^ ^^ 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> { - | ---- ^ ^ generic argument - | | | - | | generic argument - | the first constraint is provided here + | ^ ---- ---- ^ ---- ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct D> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> { - | ---- ^ ^^ ^ ^^ 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