]> git.lizzy.rs Git - rust.git/commitdiff
Include bounds in generic reordering diagnostic.
authorDavid Wood <david@davidtw.co>
Sat, 30 Mar 2019 19:30:36 +0000 (20:30 +0100)
committerDavid Wood <david@davidtw.co>
Sat, 30 Mar 2019 23:14:21 +0000 (00:14 +0100)
This commit extends the existing generic re-ordering diagnostic to
include any bounds on the generic parameter, thus producing correct
suggestions.

src/librustc_passes/ast_validation.rs
src/test/ui/issue-59508.fixed [new file with mode: 0644]
src/test/ui/issue-59508.rs [new file with mode: 0644]
src/test/ui/issue-59508.stderr [new file with mode: 0644]

index 4e2aefe623167ffdb16e967db09ada688b74ca7e..917564b17dfd04f10c62835c8fbb6d6d8986db5f 100644 (file)
@@ -361,7 +361,14 @@ enum GenericPosition {
 
 fn validate_generics_order<'a>(
     handler: &errors::Handler,
-    generics: impl Iterator<Item = (ParamKindOrd, Span, Option<String>)>,
+    generics: impl Iterator<
+        Item = (
+            ParamKindOrd,
+            Option<&'a [GenericBound]>,
+            Span,
+            Option<String>
+        ),
+    >,
     pos: GenericPosition,
     span: Span,
 ) {
@@ -369,9 +376,9 @@ fn validate_generics_order<'a>(
     let mut out_of_order = FxHashMap::default();
     let mut param_idents = vec![];
 
-    for (kind, span, ident) in generics {
+    for (kind, bounds, span, ident) in generics {
         if let Some(ident) = ident {
-            param_idents.push((kind, param_idents.len(), ident));
+            param_idents.push((kind, bounds, param_idents.len(), ident));
         }
         let max_param = &mut max_param;
         match max_param {
@@ -385,13 +392,19 @@ fn validate_generics_order<'a>(
 
     let mut ordered_params = "<".to_string();
     if !out_of_order.is_empty() {
-        param_idents.sort_by_key(|&(po, i, _)| (po, i));
+        param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
         let mut first = true;
-        for (_, _, ident) in param_idents {
+        for (_, bounds, _, ident) in param_idents {
             if !first {
                 ordered_params += ", ";
             }
             ordered_params += &ident;
+            if let Some(bounds) = bounds {
+                if !bounds.is_empty() {
+                    ordered_params += ": ";
+                    ordered_params += &pprust::bounds_to_string(&bounds);
+                }
+            }
             first = false;
         }
     }
@@ -701,7 +714,7 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
                         GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
                         GenericArg::Type(..) => ParamKindOrd::Type,
                         GenericArg::Const(..) => ParamKindOrd::Const,
-                    }, arg.span(), None)
+                    }, None, arg.span(), None)
                 }), GenericPosition::Arg, generic_args.span());
 
                 // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
@@ -736,16 +749,16 @@ fn visit_generics(&mut self, generics: &'a Generics) {
         }
 
         validate_generics_order(self.err_handler(), generics.params.iter().map(|param| {
-            let span = param.ident.span;
             let ident = Some(param.ident.to_string());
-            match &param.kind {
-                GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, span, ident),
-                GenericParamKind::Type { .. } => (ParamKindOrd::Type, span, ident),
+            let (kind, ident) = match &param.kind {
+                GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
+                GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
                 GenericParamKind::Const { ref ty } => {
                     let ty = pprust::ty_to_string(ty);
-                    (ParamKindOrd::Const, span, Some(format!("const {}: {}", param.ident, ty)))
+                    (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
                 }
-            }
+            };
+            (kind, Some(&*param.bounds), param.ident.span, ident)
         }), GenericPosition::Param, generics.span);
 
         for predicate in &generics.where_clause.predicates {
diff --git a/src/test/ui/issue-59508.fixed b/src/test/ui/issue-59508.fixed
new file mode 100644 (file)
index 0000000..b5c60a1
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<'a, 'b: 'a, T>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59508.rs b/src/test/ui/issue-59508.rs
new file mode 100644 (file)
index 0000000..0b39c5d
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59508.stderr b/src/test/ui/issue-59508.stderr
new file mode 100644 (file)
index 0000000..33e967c
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508.rs:10:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+