]> git.lizzy.rs Git - rust.git/commitdiff
Move generic arg / param validation to `create_substs_for_generic_args`
authorvarkor <github@varkor.com>
Tue, 21 Jan 2020 23:07:07 +0000 (23:07 +0000)
committervarkor <github@varkor.com>
Sat, 22 Feb 2020 00:28:18 +0000 (00:28 +0000)
21 files changed:
src/librustc_ast_passes/ast_validation.rs
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes/E0747.md [new file with mode: 0644]
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/test/ui/const-generics/const-arg-type-arg-misordered.rs [new file with mode: 0644]
src/test/ui/const-generics/const-arg-type-arg-misordered.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-after-const-literal-arg.rs [new file with mode: 0644]
src/test/ui/const-generics/const-param-after-const-literal-arg.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-before-other-params.rs
src/test/ui/const-generics/const-param-before-other-params.stderr
src/test/ui/parser/issue-14303-fncall.rs
src/test/ui/parser/issue-14303-fncall.stderr
src/test/ui/parser/issue-14303-path.rs
src/test/ui/parser/issue-14303-path.stderr
src/test/ui/suggestions/suggest-move-types.rs
src/test/ui/suggestions/suggest-move-types.stderr
src/test/ui/traits/trait-object-vs-lifetime.rs
src/test/ui/traits/trait-object-vs-lifetime.stderr

index 1194269e0ee9638af9cda5276852d70d6f744f26..d55efeda3c14afaf9f81b7a36a59a2ea9f0643ff 100644 (file)
@@ -594,23 +594,15 @@ fn check_item_named(&self, ident: Ident, kind: &str) {
     }
 }
 
-enum GenericPosition {
-    Param,
-    Arg,
-}
-
-fn validate_generics_order<'a>(
+fn validate_generic_param_order<'a>(
     sess: &Session,
     handler: &rustc_errors::Handler,
     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
-    pos: GenericPosition,
     span: Span,
 ) {
     let mut max_param: Option<ParamKindOrd> = None;
     let mut out_of_order = FxHashMap::default();
     let mut param_idents = vec![];
-    let mut found_type = false;
-    let mut found_const = false;
 
     for (kind, bounds, span, ident) in generics {
         if let Some(ident) = ident {
@@ -624,11 +616,6 @@ fn validate_generics_order<'a>(
             }
             Some(_) | None => *max_param = Some(kind),
         };
-        match kind {
-            ParamKindOrd::Type => found_type = true,
-            ParamKindOrd::Const => found_const = true,
-            _ => {}
-        }
     }
 
     let mut ordered_params = "<".to_string();
@@ -651,42 +638,26 @@ fn validate_generics_order<'a>(
     }
     ordered_params += ">";
 
-    let pos_str = match pos {
-        GenericPosition::Param => "parameter",
-        GenericPosition::Arg => "argument",
-    };
-
     for (param_ord, (max_param, spans)) in &out_of_order {
-        let mut err = handler.struct_span_err(
-            spans.clone(),
-            &format!(
-                "{} {pos}s must be declared prior to {} {pos}s",
-                param_ord,
-                max_param,
-                pos = pos_str,
-            ),
-        );
-        if let GenericPosition::Param = pos {
-            err.span_suggestion(
-                span,
+        let mut err =
+            handler.struct_span_err(
+                spans.clone(),
                 &format!(
-                    "reorder the {}s: lifetimes, then types{}",
-                    pos_str,
-                    if sess.features_untracked().const_generics { ", then consts" } else { "" },
+                    "{} parameters must be declared prior to {} parameters",
+                    param_ord, max_param,
                 ),
-                ordered_params.clone(),
-                Applicability::MachineApplicable,
             );
-        }
+        err.span_suggestion(
+            span,
+            &format!(
+                "reorder the parameters: lifetimes, then types{}",
+                if sess.features_untracked().const_generics { ", then consts" } else { "" },
+            ),
+            ordered_params.clone(),
+            Applicability::MachineApplicable,
+        );
         err.emit();
     }
-
-    // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
-    // if we don't. Const parameters and type parameters can currently conflict if they
-    // are out-of-order.
-    if !out_of_order.is_empty() && found_type && found_const {
-        FatalError.raise();
-    }
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
@@ -1000,24 +971,6 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
         match *generic_args {
             GenericArgs::AngleBracketed(ref data) => {
                 walk_list!(self, visit_generic_arg, &data.args);
-                validate_generics_order(
-                    self.session,
-                    self.err_handler(),
-                    data.args.iter().map(|arg| {
-                        (
-                            match arg {
-                                GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
-                                GenericArg::Type(..) => ParamKindOrd::Type,
-                                GenericArg::Const(..) => ParamKindOrd::Const,
-                            },
-                            None,
-                            arg.span(),
-                            None,
-                        )
-                    }),
-                    GenericPosition::Arg,
-                    generic_args.span(),
-                );
 
                 // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
                 // are allowed to contain nested `impl Trait`.
@@ -1054,7 +1007,7 @@ fn visit_generics(&mut self, generics: &'a Generics) {
             }
         }
 
-        validate_generics_order(
+        validate_generic_param_order(
             self.session,
             self.err_handler(),
             generics.params.iter().map(|param| {
@@ -1069,7 +1022,6 @@ fn visit_generics(&mut self, generics: &'a Generics) {
                 };
                 (kind, Some(&*param.bounds), param.ident.span, ident)
             }),
-            GenericPosition::Param,
             generics.span,
         );
 
index ba43b29538d50dcd85b5f42ed14ed637251adb9d..91a7b6c8958382bab398372bec9c093e590339b4 100644 (file)
 E0744: include_str!("./error_codes/E0744.md"),
 E0745: include_str!("./error_codes/E0745.md"),
 E0746: include_str!("./error_codes/E0746.md"),
+E0747: include_str!("./error_codes/E0747.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0747.md b/src/librustc_error_codes/error_codes/E0747.md
new file mode 100644 (file)
index 0000000..45b2dfd
--- /dev/null
@@ -0,0 +1,10 @@
+Generic arguments must be provided in the same order as the corresponding generic
+parameters are declared.
+
+Erroneous code example:
+
+```compile_fail,E0747
+struct S<'a, T>(&'a T);
+
+type X = S<(), 'static>; // error: the type argument is provided before the lifetime argument
+```
index 1e5e00445cccaf36d73779abee93f20420dc4540..4ef732a7662a77646b6dda86c74afb70b58493da 100644 (file)
@@ -481,6 +481,7 @@ pub fn create_substs_for_generic_args<'b>(
         parent_substs: &[subst::GenericArg<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
+        arg_count_mismatch: bool,
         args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
         provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
         mut inferred_kind: impl FnMut(
@@ -504,7 +505,6 @@ pub fn create_substs_for_generic_args<'b>(
         // methods in `subst.rs`, so that we can iterate over the arguments and
         // parameters in lock-step linearly, instead of trying to match each pair.
         let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
-
         // Iterate over each segment of the path.
         while let Some((def_id, defs)) = stack.pop() {
             let mut params = defs.params.iter().peekable();
@@ -541,6 +541,18 @@ pub fn create_substs_for_generic_args<'b>(
             let mut args =
                 generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
 
+            let arg_kind = |arg| match arg {
+                &GenericArg::Lifetime(_) => "lifetime",
+                &GenericArg::Type(_) => "type",
+                &GenericArg::Const(_) => "constant",
+            };
+
+            // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
+            // If we later encounter a lifetime, we know that the arguments were provided in the
+            // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
+            // inferred, so we can use it for diagnostics later.
+            let mut force_infer_lt = None;
+
             loop {
                 // We're going to iterate through the generic arguments that the user
                 // provided, matching them with the generic parameters we expect.
@@ -561,28 +573,74 @@ pub fn create_substs_for_generic_args<'b>(
                                 // We expected a lifetime argument, but got a type or const
                                 // argument. That means we're inferring the lifetimes.
                                 substs.push(inferred_kind(None, param, infer_args));
+                                force_infer_lt = Some(arg);
                                 params.next();
                             }
-                            (_, _) => {
+                            (_, kind) => {
                                 // We expected one kind of parameter, but the user provided
-                                // another. This is an error, but we need to handle it
-                                // gracefully so we can report sensible errors.
-                                // In this case, we're simply going to infer this argument.
-                                args.next();
+                                // another. This is an error. However, if we already know that
+                                // the arguments don't match up with the parameters, we won't issue
+                                // an additional error, as the user already knows what's wrong.
+                                if !arg_count_mismatch {
+                                    let param_kind = match kind {
+                                        GenericParamDefKind::Lifetime => "lifetime",
+                                        GenericParamDefKind::Type { .. } => "type",
+                                        GenericParamDefKind::Const => "constant",
+                                    };
+                                    struct_span_err!(
+                                        tcx.sess,
+                                        arg.span(),
+                                        E0747,
+                                        "{} provided when a {} was expected",
+                                        arg_kind(arg),
+                                        param_kind,
+                                    )
+                                    .emit();
+                                }
+
+                                // We've reported the error, but we want to make sure that this
+                                // problem doesn't bubble down and create additional, irrelevant
+                                // errors. In this case, we're simply going to ignore the argument
+                                // and any following arguments. The rest of the parameters will be
+                                // inferred.
+                                while args.next().is_some() {}
                             }
                         }
                     }
-                    (Some(_), None) => {
+                    (Some(&arg), None) => {
                         // We should never be able to reach this point with well-formed input.
-                        // Getting to this point means the user supplied more arguments than
-                        // there are parameters.
-                        args.next();
+                        // There are two situations in which we can encounter this issue.
+                        //
+                        //  1.  The number of arguments is incorrect. In this case, an error
+                        //      will already have been emitted, and we can ignore it. This case
+                        //      also occurs when late-bound lifetime parameters are present, yet
+                        //      the lifetime arguments have also been explicitly specified by the
+                        //      user.
+                        //  2.  We've inferred some lifetimes, which have been provided later (i.e.
+                        //      after a type or const). We want to throw an error in this case.
+
+                        if !arg_count_mismatch {
+                            let kind = arg_kind(arg);
+                            assert_eq!(kind, "lifetime");
+                            let provided =
+                                force_infer_lt.expect("lifetimes ought to have been inferred");
+                            struct_span_err!(
+                                tcx.sess,
+                                provided.span(),
+                                E0747,
+                                "{} provided when a {} was expected",
+                                arg_kind(provided),
+                                kind,
+                            )
+                            .emit();
+                        }
+
+                        break;
                     }
                     (None, Some(&param)) => {
                         // If there are fewer arguments than parameters, it means
                         // we're inferring the remaining arguments.
                         substs.push(inferred_kind(Some(&substs), param, infer_args));
-                        args.next();
                         params.next();
                     }
                     (None, None) => break,
@@ -658,7 +716,7 @@ fn create_substs_for_ast_path<'a>(
             assert!(self_ty.is_none() && parent_substs.is_empty());
         }
 
-        let (_, potential_assoc_types) = Self::check_generic_arg_count(
+        let (arg_count_mismatch, potential_assoc_types) = Self::check_generic_arg_count(
             tcx,
             span,
             &generic_params,
@@ -691,6 +749,7 @@ fn create_substs_for_ast_path<'a>(
             parent_substs,
             self_ty.is_some(),
             self_ty,
+            arg_count_mismatch,
             // Provide the generic args, and whether types should be inferred.
             |did| {
                 if did == def_id {
index 04cbee8c94061ac77e946e285b09591759deb85a..e3fde9159cc38257993f2941dd70faa7cdcbc012 100644 (file)
@@ -299,7 +299,7 @@ fn instantiate_method_substs(
         // If they were not explicitly supplied, just construct fresh
         // variables.
         let generics = self.tcx.generics_of(pick.item.def_id);
-        AstConv::check_generic_arg_count_for_call(
+        let arg_count_mismatch = AstConv::check_generic_arg_count_for_call(
             self.tcx, self.span, &generics, &seg, true, // `is_method_call`
         );
 
@@ -313,6 +313,7 @@ fn instantiate_method_substs(
             parent_substs,
             false,
             None,
+            arg_count_mismatch,
             // Provide the generic args, and whether types should be inferred.
             |def_id| {
                 // The last component of the returned tuple here is unimportant.
index 4f6eb20e6ebbd77e0f4702f3cb8ea27426adc603..989f98682f93e31d16205d43217afce3686054ef 100644 (file)
@@ -5520,6 +5520,7 @@ pub fn instantiate_value_path(
                 &[][..],
                 has_self,
                 self_ty,
+                !infer_args_for_err.is_empty(),
                 // Provide the generic args, and whether types should be inferred.
                 |def_id| {
                     if let Some(&PathSeg(_, index)) =
index 70586be0d04336964f9d6f49ddda10a43cb54d4c..3bdec71d3dcf702c51a356ad7ceeff15eb1f2b6f 100644 (file)
@@ -1269,7 +1269,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 
     let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
 
-    // Now create the real type parameters.
+    // Now create the real type and const parameters.
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
     params.extend(ast_generics.params.iter().filter_map(|param| {
diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs
new file mode 100644 (file)
index 0000000..f024eb6
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+type Array<T, const N: usize> = [T; N];
+
+fn foo<const N: usize>() -> Array<N, ()> { //~ ERROR constant provided when a type was expected
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr
new file mode 100644 (file)
index 0000000..225e1cd
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-arg-type-arg-misordered.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0747]: constant provided when a type was expected
+  --> $DIR/const-arg-type-arg-misordered.rs:6:35
+   |
+LL | fn foo<const N: usize>() -> Array<N, ()> {
+   |                                   ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs
new file mode 100644 (file)
index 0000000..683bcc8
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Foo<const A: usize, const B: usize>;
+
+impl<const A: usize> Foo<1, A> {} // ok
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr b/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr
new file mode 100644 (file)
index 0000000..a949a6e
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-after-const-literal-arg.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
index 5bdbfd8ff1f3907ba6dce0faaa0004261a8c2c76..2c81681b85e7ddfb6cc9e07e530e67e77dcf9b76 100644 (file)
@@ -1,4 +1,5 @@
 #![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
 fn bar<const X: (), 'a>(_: &'a ()) {
     //~^ ERROR lifetime parameters must be declared prior to const parameters
index 87622f7e50010d5c57a282cd515164afeccffcd3..fccf732de4c9991f2f99c25d77664520692bd7a7 100644 (file)
@@ -1,14 +1,22 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/const-param-before-other-params.rs:3:21
+  --> $DIR/const-param-before-other-params.rs:4:21
    |
 LL | fn bar<const X: (), 'a>(_: &'a ()) {
    |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
 
 error: type parameters must be declared prior to const parameters
-  --> $DIR/const-param-before-other-params.rs:7:21
+  --> $DIR/const-param-before-other-params.rs:8:21
    |
 LL | fn foo<const X: (), T>(_: &T) {
    |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
 
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param-before-other-params.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
 error: aborting due to 2 previous errors
 
index 39694198cdb4d1807fac4bbb2438c4664dc681f0..46ece84d69e457ae97084e56f27a9c9785f50694 100644 (file)
@@ -11,7 +11,7 @@ fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
     let _x = (*start..*end)
         .map(|x| S { a: start, b: end })
         .collect::<Vec<S<_, 'a>>>();
-        //~^ ERROR lifetime arguments must be declared prior to type arguments
+        //~^ ERROR type provided when a lifetime was expected
 }
 
 fn main() {}
index 8ef9f1a1a6c79edcb1533627a2aafb7cbdc08628..cdda0d001c7dc575c7fb5f49c8aa86f4edebfad6 100644 (file)
@@ -1,8 +1,9 @@
-error: lifetime arguments must be declared prior to type arguments
-  --> $DIR/issue-14303-fncall.rs:13:29
+error[E0747]: type provided when a lifetime was expected
+  --> $DIR/issue-14303-fncall.rs:13:26
    |
 LL |         .collect::<Vec<S<_, 'a>>>();
-   |                             ^^
+   |                          ^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0747`.
index 386d19859e4a83d6a6055ee2e295f4d6023df6cc..89ef914aba238a7871241e1ccf7b860c87f7460e 100644 (file)
@@ -8,6 +8,6 @@ pub struct X<'a, 'b, 'c, T> {
 }
 
 fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
-//~^ ERROR lifetime arguments must be declared prior to type arguments
+//~^ ERROR type provided when a lifetime was expected
 
 fn main() {}
index 19f2995ebee536e652d98662d357b6bca4ea263c..841e63ecbe9d5128c40f5d27ebed08470bc57375 100644 (file)
@@ -1,8 +1,9 @@
-error: lifetime arguments must be declared prior to type arguments
-  --> $DIR/issue-14303-path.rs:10:40
+error[E0747]: type provided when a lifetime was expected
+  --> $DIR/issue-14303-path.rs:10:37
    |
 LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
-   |                                        ^^  ^^
+   |                                     ^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0747`.
index 890950ea08c5d4a316475b95181f3a28832975ef..6505a97de6e4bfcbb8c556fd01d9476b133e0be5 100644 (file)
@@ -33,7 +33,7 @@ struct A<T, M: One<A=(), T>> { //~ ERROR associated type bindings must be declar
 
 struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
 //~^ ERROR associated type bindings must be declared after generic parameters
-//~^^ ERROR lifetime arguments must be declared prior to type arguments
+//~^^ ERROR type provided when a lifetime was expected
     m: M,
     t: &'a T,
 }
@@ -47,7 +47,7 @@ struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { //~ ERROR associated ty
 
 struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
 //~^ ERROR associated type bindings must be declared after generic parameters
-//~^^ ERROR lifetime arguments must be declared prior to type arguments
+//~^^ ERROR type provided when a lifetime was expected
     m: M,
     t: &'a T,
     u: &'b U,
@@ -63,7 +63,7 @@ struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { //~ ERROR associated ty
 
 struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
 //~^ ERROR associated type bindings must be declared after generic parameters
-//~^^ ERROR lifetime arguments must be declared prior to type arguments
+//~^^ ERROR lifetime provided when a type was expected
     m: M,
     t: &'a T,
     u: &'b U,
@@ -79,7 +79,7 @@ struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { //~ ERROR associated ty
 
 struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
 //~^ ERROR associated type bindings must be declared after generic parameters
-//~^^ ERROR lifetime arguments must be declared prior to type arguments
+//~^^ ERROR lifetime provided when a type was expected
     m: M,
     t: &'a T,
     u: &'b U,
index 552fb78cd3fddd5d7ad34577200925ca21941373..07ad1a3150836e0f418dfa676d2d16f392aeaec0 100644 (file)
@@ -74,29 +74,30 @@ LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, '
    |                                                            |     this associated type binding should be moved after the generic parameters
    |                                                            this associated type binding should be moved after the generic parameters
 
-error: lifetime arguments must be declared prior to type arguments
-  --> $DIR/suggest-move-types.rs:34:46
+error[E0747]: type provided when a lifetime was expected
+  --> $DIR/suggest-move-types.rs:34:43
    |
 LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
-   |                                              ^^
+   |                                           ^
 
-error: lifetime arguments must be declared prior to type arguments
-  --> $DIR/suggest-move-types.rs:48:80
+error[E0747]: type provided when a lifetime was expected
+  --> $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>> {
-   |                                                                                ^^  ^^  ^^
+   |                                                                       ^
 
-error: lifetime arguments must be declared prior to type arguments
+error[E0747]: lifetime provided when a type was expected
   --> $DIR/suggest-move-types.rs:64:56
    |
 LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
-   |                                                        ^^                       ^^     ^^
+   |                                                        ^^
 
-error: lifetime arguments must be declared prior to type arguments
+error[E0747]: lifetime provided when a type was expected
   --> $DIR/suggest-move-types.rs:80:56
    |
 LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
-   |                                                        ^^                 ^^           ^^
+   |                                                        ^^
 
 error: aborting due to 12 previous errors
 
+For more information about this error, try `rustc --explain E0747`.
index e0ff73494837613385ab9b6b6ef3cdbb309382e0..e885cd2f68ac5bbed55e1ced305c729cd34ef060 100644 (file)
@@ -12,6 +12,6 @@ fn main() {
     //~^ ERROR wrong number of lifetime arguments: expected 1, found 2
     //~| ERROR wrong number of type arguments: expected 1, found 0
     let _: S<dyn 'static +, 'static>;
-    //~^ ERROR lifetime arguments must be declared prior to type arguments
+    //~^ ERROR type provided when a lifetime was expected
     //~| ERROR at least one trait is required for an object type
 }
index be1958770a426b73fa5b22e83d0a4581b7f3e6b1..d1e5a65c0ad683056681b6a785a4bbb00dd3994a 100644 (file)
@@ -1,9 +1,3 @@
-error: lifetime arguments must be declared prior to type arguments
-  --> $DIR/trait-object-vs-lifetime.rs:14:29
-   |
-LL |     let _: S<dyn 'static +, 'static>;
-   |                             ^^^^^^^
-
 error[E0224]: at least one trait is required for an object type
   --> $DIR/trait-object-vs-lifetime.rs:9:23
    |
@@ -28,6 +22,13 @@ error[E0224]: at least one trait is required for an object type
 LL |     let _: S<dyn 'static +, 'static>;
    |              ^^^^^^^^^^^^^
 
+error[E0747]: type provided when a lifetime was expected
+  --> $DIR/trait-object-vs-lifetime.rs:14:14
+   |
+LL |     let _: S<dyn 'static +, 'static>;
+   |              ^^^^^^^^^^^^^
+
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0107, E0747.
+For more information about an error, try `rustc --explain E0107`.