]> git.lizzy.rs Git - rust.git/commitdiff
Handle variadic function types
authorNick Cameron <ncameron@mozilla.com>
Mon, 11 Apr 2016 09:20:03 +0000 (21:20 +1200)
committerNick Cameron <ncameron@mozilla.com>
Mon, 11 Apr 2016 22:47:35 +0000 (10:47 +1200)
Closes #842

src/expr.rs
src/types.rs
tests/source/type.rs
tests/target/type.rs

index 7ee69885a429da8f58ab2b037e10b7e13821871b..0c30aaf3f6fec3d2f69e4265aa787705ae4f6203 100644 (file)
@@ -981,7 +981,7 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Opt
                                     .collect::<Option<Vec<_>>>());
 
         let all_simple = pat_strs.iter().all(|p| pat_is_simple(&p));
-        let items: Vec<_> = pat_strs.into_iter().map(|s| ListItem::from_str(s)).collect();
+        let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
         let fmt = ListFormatting {
             tactic: if all_simple {
                 DefinitiveListTactic::Mixed
index 51bebc409e09ed3c8f85ec15c7ed5bcc4a532973..09cf7e12126c1fe4756b3f686dbb163fa38886d1 100644 (file)
@@ -220,6 +220,7 @@ fn rewrite_segment(expr_context: bool,
             };
             try_opt!(format_function_type(data.inputs.iter().map(|x| &**x),
                                           &output,
+                                          false,
                                           data.span,
                                           context,
                                           width,
@@ -233,6 +234,7 @@ fn rewrite_segment(expr_context: bool,
 
 fn format_function_type<'a, I>(inputs: I,
                                output: &FunctionRetTy,
+                               variadic: bool,
                                span: Span,
                                context: &RewriteContext,
                                width: usize,
@@ -242,17 +244,54 @@ fn format_function_type<'a, I>(inputs: I,
           <I as Iterator>::Item: Deref,
           <I::Item as Deref>::Target: Rewrite + Spanned + 'a
 {
+    // Code for handling variadics is somewhat duplicated for items, but they
+    // are different enough to need some serious refactoring to share code.
+    enum ArgumentKind<T>
+        where T: Deref,
+              <T as Deref>::Target: Rewrite + Spanned
+    {
+        Regular(Box<T>),
+        Variadic(BytePos),
+    }
+
+    let variadic_arg = if variadic {
+        let variadic_start = context.codemap.span_before(span, "...");
+        Some(ArgumentKind::Variadic(variadic_start))
+    } else {
+        None
+    };
+
     // 2 for ()
     let budget = try_opt!(width.checked_sub(2));
     // 1 for (
     let offset = offset + 1;
     let list_lo = context.codemap.span_after(span, "(");
     let items = itemize_list(context.codemap,
-                             inputs,
+                             // FIXME Would be nice to avoid this allocation,
+                             // but I couldn't get the types to work out.
+                             inputs.map(|i| ArgumentKind::Regular(Box::new(i)))
+                                   .chain(variadic_arg),
                              ")",
-                             |ty| ty.span().lo,
-                             |ty| ty.span().hi,
-                             |ty| ty.rewrite(context, budget, offset),
+                             |arg| {
+                                 match *arg {
+                                     ArgumentKind::Regular(ref ty) => ty.span().lo,
+                                     ArgumentKind::Variadic(start) => start,
+                                 }
+                             },
+                             |arg| {
+                                 match *arg {
+                                     ArgumentKind::Regular(ref ty) => ty.span().hi,
+                                     ArgumentKind::Variadic(start) => start + BytePos(3),
+                                 }
+                             },
+                             |arg| {
+                                 match *arg {
+                                     ArgumentKind::Regular(ref ty) => {
+                                         ty.rewrite(context, budget, offset)
+                                     }
+                                     ArgumentKind::Variadic(_) => Some("...".to_owned()),
+                                 }
+                             },
                              list_lo,
                              span.hi);
 
@@ -579,6 +618,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
 
     let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(),
                                                 &bare_fn.decl.output,
+                                                bare_fn.decl.variadic,
                                                 span,
                                                 context,
                                                 budget,
index 71822bd668dc0504bb7c8ad56c6a7f8039a9915f..dcb8e0d0f31ad7dbbb2ccef510b6c0050bef0052 100644 (file)
@@ -4,3 +4,11 @@ fn types() {
     let z: (/*#digits*/ usize, /*exp*/ i16) = funk();
     let z: ( usize  /*#digits*/ , i16 /*exp*/ ) = funk();
 }
+
+struct F {
+    f: extern "C" fn(x: u8, ... /* comment */),
+    g: extern "C" fn(x: u8,/* comment */ ...),
+    h: extern "C" fn(x: u8, ... ),
+    i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3
+                     z: Foo, /* comment */ .../* comment 2*/ ),
+}
index a8a5e028aa5cc5d5386364d9f1df6ef8acab7be3..1ae1143bccaeecd9fda11404476f8d52707f3357 100644 (file)
@@ -7,3 +7,17 @@ fn types() {
             i16) = funk();
     let z: (usize /* #digits */, i16 /* exp */) = funk();
 }
+
+struct F {
+    f: extern "C" fn(x: u8, ... /* comment */),
+    g: extern "C" fn(x: u8,
+                     // comment
+                     ...),
+    h: extern "C" fn(x: u8, ...),
+    i: extern "C" fn(x: u8,
+                     // comment 4
+                     y: String, // comment 3
+                     z: Foo,
+                     // comment
+                     ... /* comment 2 */),
+}