]> git.lizzy.rs Git - rust.git/blobdiff - src/chains.rs
Merge pull request #2043 from sunjay/lift_generics
[rust.git] / src / chains.rs
index e5450aa687e46e4666ea73ac0fa97f07324c41f7..20e0be36fe406d3013e61bdc5e0732abb36f3e3c 100644 (file)
 /// alignment).
 /// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the
 /// following values of `chain_indent`:
+/// Block:
+/// ```
+/// let foo = {
+///     aaaa;
+///     bbb;
+///     ccc
+/// }.bar
+///     .baz();
+/// ```
 /// Visual:
 /// ```
 /// let foo = {
 ///           .bar
 ///           .baz();
 /// ```
-/// Inherit:
-/// ```
-/// let foo = {
-///     aaaa;
-///     bbb;
-///     ccc
-/// }
-/// .bar
-/// .baz();
-/// ```
-/// Tabbed:
-/// ```
-/// let foo = {
-///         aaaa;
-///         bbb;
-///         ccc
-///     }
-///     .bar
-///     .baz();
-/// ```
 ///
 /// If the first item in the chain is a block expression, we align the dots with
 /// the braces.
-/// Visual:
-/// ```
-/// let a = foo.bar
-///            .baz()
-///            .qux
-/// ```
-/// Inherit:
+/// Block:
 /// ```
 /// let a = foo.bar
-/// .baz()
-/// .qux
+///     .baz()
+///     .qux
 /// ```
-/// Tabbed:
+/// Visual:
 /// ```
 /// let a = foo.bar
-///     .baz()
-///     .qux
+///            .baz()
+///            .qux
 /// ```
 
-use Shape;
-use rewrite::{Rewrite, RewriteContext};
-use utils::{wrap_str, first_line_width, last_line_width};
-use expr::rewrite_call;
+use shape::Shape;
 use config::IndentStyle;
+use expr::rewrite_call;
 use macros::convert_try_mac;
+use rewrite::{Rewrite, RewriteContext};
+use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp,
+            trimmed_last_line_width, wrap_str};
 
 use std::cmp::min;
 use std::iter;
 use syntax::{ast, ptr};
-use syntax::codemap::{mk_sp, Span};
+use syntax::codemap::Span;
 
 pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option<String> {
     debug!("rewrite_chain {:?}", shape);
@@ -98,41 +82,31 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
     if chain_only_try(&subexpr_list) {
         return rewrite_try(&parent, subexpr_list.len(), context, shape);
     }
-    let trailing_try_num = subexpr_list
-        .iter()
-        .take_while(|e| match e.node {
-                        ast::ExprKind::Try(..) => true,
-                        _ => false,
-                    })
-        .count();
+    let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count();
+    let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count();
 
     // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`.
     let parent_shape = if is_block_expr(context, &parent, "\n") {
         match context.config.chain_indent() {
             IndentStyle::Visual => shape.visual_indent(0),
-            IndentStyle::Block => shape.block(),
+            IndentStyle::Block => shape,
         }
     } else {
         shape
     };
-    let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape));
+    let parent_rewrite = parent
+        .rewrite(context, parent_shape)
+        .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?;
     let parent_rewrite_contains_newline = parent_rewrite.contains('\n');
+    let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces();
 
     // Decide how to layout the rest of the chain. `extend` is true if we can
     // put the first non-parent item on the same line as the parent.
-    let first_subexpr_is_try = match subexpr_list.last().unwrap().node {
-        ast::ExprKind::Try(..) => true,
-        _ => false,
-    };
     let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) {
-        let nested_shape = if first_subexpr_is_try {
-            parent_shape.block_indent(context.config.tab_spaces())
-        } else {
-            chain_indent(context, shape.add_offset(parent_rewrite.len()))
-        };
-        (nested_shape,
-         context.config.chain_indent() == IndentStyle::Visual ||
-         parent_rewrite.len() <= context.config.tab_spaces())
+        (
+            chain_indent(context, shape.add_offset(parent_rewrite.len())),
+            context.config.chain_indent() == IndentStyle::Visual || is_small_parent,
+        )
     } else if is_block_expr(context, &parent, &parent_rewrite) {
         match context.config.chain_indent() {
             // Try to put the first child on the same line with parent's last line
@@ -141,195 +115,219 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
             // brace.
             IndentStyle::Visual => (parent_shape, false),
         }
-    } else if parent_rewrite_contains_newline {
-        (chain_indent(context, parent_shape), false)
     } else {
-        (shape.block_indent(context.config.tab_spaces()), false)
+        (
+            chain_indent(context, shape.add_offset(parent_rewrite.len())),
+            false,
+        )
     };
 
     let other_child_shape = nested_shape.with_max_width(context.config);
 
     let first_child_shape = if extend {
         let overhead = last_line_width(&parent_rewrite);
-        let offset = parent_rewrite.lines().rev().next().unwrap().trim().len();
+        let offset = trimmed_last_line_width(&parent_rewrite);
         match context.config.chain_indent() {
-            IndentStyle::Visual => try_opt!(parent_shape.offset_left(overhead)),
-            IndentStyle::Block => try_opt!(parent_shape.block().offset_left(offset)),
+            IndentStyle::Visual => parent_shape.offset_left(overhead)?,
+            IndentStyle::Block => parent_shape.block().offset_left(offset)?,
         }
     } else {
         other_child_shape
     };
-    debug!("child_shapes {:?} {:?}",
-           first_child_shape,
-           other_child_shape);
+    debug!(
+        "child_shapes {:?} {:?}",
+        first_child_shape,
+        other_child_shape
+    );
 
     let child_shape_iter = Some(first_child_shape)
         .into_iter()
-        .chain(::std::iter::repeat(other_child_shape)
-                   .take(subexpr_list.len() - 1));
-    let iter = subexpr_list.iter().rev().zip(child_shape_iter);
-    let mut rewrites = try_opt!(iter.map(|(e, shape)| {
-                                             rewrite_chain_subexpr(e, total_span, context, shape)
-                                         })
-                                    .collect::<Option<Vec<_>>>());
+        .chain(iter::repeat(other_child_shape));
+    let subexpr_num = subexpr_list.len();
+    let last_subexpr = &subexpr_list[suffix_try_num];
+    let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num];
+    let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter);
+    let mut rewrites = iter.map(|(e, shape)| {
+        rewrite_chain_subexpr(e, total_span, context, shape)
+    }).collect::<Option<Vec<_>>>()?;
 
     // Total of all items excluding the last.
-    let last_non_try_index = rewrites.len() - (1 + trailing_try_num);
-    let almost_total = rewrites[..last_non_try_index]
-        .iter()
-        .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len();
-    let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) +
-                       parent_rewrite.len();
-
-    let one_line_budget = min(shape.width, context.config.chain_one_line_max());
-    let veto_single_line = if one_line_len > one_line_budget {
-        if rewrites.len() > 1 {
-            true
-        } else if rewrites.len() == 1 {
-            parent_rewrite.len() > context.config.chain_one_line_max() / 2
-        } else {
-            false
-        }
-    } else if context.config.take_source_hints() && subexpr_list.len() > 1 {
-        // Look at the source code. Unless all chain elements start on the same
-        // line, we won't consider putting them on a single line either.
-        let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi));
-        let first_span = context.snippet(subexpr_list[1].span);
-        let last_iter = last_span.chars().take_while(|c| c.is_whitespace());
-
-        first_span.chars().chain(last_iter).any(|c| c == '\n')
+    let extend_last_subexr = last_line_extendable(&parent_rewrite) && rewrites.is_empty();
+    let almost_total = if extend_last_subexr {
+        last_line_width(&parent_rewrite)
     } else {
-        false
+        rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len()
+    } + suffix_try_num;
+    let one_line_budget = if rewrites.is_empty() && !context.config.chain_split_single_child() {
+        shape.width
+    } else {
+        min(shape.width, context.config.chain_one_line_max())
     };
-
-    let mut fits_single_line = !veto_single_line && almost_total <= shape.width;
-    if fits_single_line {
-        let len = rewrites.len();
-        let (init, last) = rewrites.split_at_mut(len - (1 + trailing_try_num));
-        fits_single_line = init.iter().all(|s| !s.contains('\n'));
-
-        if fits_single_line {
-            fits_single_line = match expr.node {
-                ref e @ ast::ExprKind::MethodCall(..) => {
-                    if rewrite_method_call_with_overflow(e,
-                                                         &mut last[0],
-                                                         almost_total,
-                                                         total_span,
-                                                         context,
-                                                         shape) {
-                        // If the first line of the last method does not fit into a single line
-                        // after the others, allow new lines.
-                        almost_total + first_line_width(&last[0]) < context.config.max_width()
-                    } else {
-                        false
+    let all_in_one_line = !parent_rewrite_contains_newline
+        && rewrites.iter().all(|s| !s.contains('\n'))
+        && almost_total < one_line_budget;
+    let last_shape = match context.config.chain_indent() {
+        IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?,
+        IndentStyle::Block => other_child_shape,
+    };
+    let last_shape = last_shape.sub_width(suffix_try_num)?;
+
+    // Rewrite the last child. The last child of a chain requires special treatment. We need to
+    // know whether 'overflowing' the last child make a better formatting:
+    //
+    // A chain with overflowing the last child:
+    // ```
+    // parent.child1.child2.last_child(
+    //     a,
+    //     b,
+    //     c,
+    // )
+    // ```
+    //
+    // A chain without overflowing the last child (in vertical layout):
+    // ```
+    // parent
+    //     .child1
+    //     .child2
+    //     .last_child(a, b, c)
+    // ```
+    //
+    // In particular, overflowing is effective when the last child is a method with a multi-lined
+    // block-like argument (e.g. closure):
+    // ```
+    // parent.child1.chlid2.last_child(|a, b, c| {
+    //     let x = foo(a, b, c);
+    //     let y = bar(a, b, c);
+    //
+    //     // ...
+    //
+    //     result
+    // })
+    // ```
+
+    // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of
+    // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup.
+    let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape);
+    let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr {
+        // First we try to 'overflow' the last child and see if it looks better than using
+        // vertical layout.
+        parent_shape.offset_left(almost_total).map(|shape| {
+            if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) {
+                // We allow overflowing here only if both of the following conditions match:
+                // 1. The entire chain fits in a single line expect the last child.
+                // 2. `last_chlid_str.lines().count() >= 5`.
+                let line_count = rw.lines().count();
+                let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget;
+                if fits_single_line && line_count >= 5 {
+                    (Some(rw), true)
+                } else {
+                    // We could not know whether overflowing is better than using vertical layout,
+                    // just by looking at the overflowed rewrite. Now we rewrite the last child
+                    // on its own line, and compare two rewrites to choose which is better.
+                    match rewrite_last() {
+                        Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false),
+                        Some(ref new_rw) if new_rw.lines().count() >= line_count => {
+                            (Some(rw), fits_single_line)
+                        }
+                        new_rw @ Some(..) => (new_rw, false),
+                        _ => (Some(rw), fits_single_line),
                     }
                 }
-                _ => !last[0].contains('\n'),
+            } else {
+                (rewrite_last(), false)
             }
-        }
-    }
-
-    // Try overflowing the last element if we are using block indent.
-    if !fits_single_line && context.config.fn_call_style() == IndentStyle::Block {
-        let (init, last) = rewrites.split_at_mut(last_non_try_index);
-        let almost_single_line = init.iter().all(|s| !s.contains('\n'));
-        if almost_single_line {
-            let overflow_shape = Shape {
-                width: one_line_budget,
-                ..parent_shape
-            };
-            fits_single_line = rewrite_last_child_with_overflow(context,
-                                                                &subexpr_list[trailing_try_num],
-                                                                overflow_shape,
-                                                                total_span,
-                                                                almost_total,
-                                                                one_line_budget,
-                                                                &mut last[0]);
-        }
-    }
+        })?
+    } else {
+        (rewrite_last(), false)
+    };
+    rewrites.push(last_subexpr_str?);
 
     let connector = if fits_single_line && !parent_rewrite_contains_newline {
         // Yay, we can put everything on one line.
         String::new()
     } else {
         // Use new lines.
+        if context.force_one_line_chain {
+            return None;
+        }
         format!("\n{}", nested_shape.indent.to_string(context.config))
     };
 
-    let first_connector = if subexpr_list.is_empty() {
+    let first_connector = if is_small_parent || fits_single_line
+        || last_line_extendable(&parent_rewrite)
+        || context.config.chain_indent() == IndentStyle::Visual
+    {
         ""
-    } else if extend || first_subexpr_is_try {
-        // 1 = ";", being conservative here.
-        if last_line_width(&parent_rewrite) + first_line_width(&rewrites[0]) + 1 <=
-           context.config.max_width() {
+    } else {
+        connector.as_str()
+    };
+
+    let result = if is_small_parent && rewrites.len() > 1 {
+        let second_connector = if fits_single_line || rewrites[1] == "?"
+            || last_line_extendable(&rewrites[0])
+            || context.config.chain_indent() == IndentStyle::Visual
+        {
             ""
         } else {
-            &*connector
-        }
+            &connector
+        };
+        format!(
+            "{}{}{}{}{}",
+            parent_rewrite,
+            first_connector,
+            rewrites[0],
+            second_connector,
+            join_rewrites(&rewrites[1..], &connector)
+        )
     } else {
-        &*connector
+        format!(
+            "{}{}{}",
+            parent_rewrite,
+            first_connector,
+            join_rewrites(&rewrites, &connector)
+        )
     };
-
-    wrap_str(format!("{}{}{}",
-                     parent_rewrite,
-                     first_connector,
-                     join_rewrites(&rewrites, &subexpr_list, &connector)),
-             context.config.max_width(),
-             shape)
+    let result = format!("{}{}", result, repeat_try(suffix_try_num));
+    if context.config.chain_indent() == IndentStyle::Visual {
+        wrap_str(result, context.config.max_width(), shape)
+    } else {
+        Some(result)
+    }
 }
 
 // True if the chain is only `?`s.
 fn chain_only_try(exprs: &[ast::Expr]) -> bool {
     exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node {
-                         true
-                     } else {
-                         false
-                     })
+        true
+    } else {
+        false
+    })
 }
 
 // Try to rewrite and replace the last non-try child. Return `true` if
 // replacing succeeds.
-fn rewrite_last_child_with_overflow(context: &RewriteContext,
-                                    expr: &ast::Expr,
-                                    shape: Shape,
-                                    span: Span,
-                                    almost_total: usize,
-                                    one_line_budget: usize,
-                                    last_child: &mut String)
-                                    -> bool {
-    if let Some(shape) = shape.shrink_left(almost_total) {
-        if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) {
-            if almost_total + first_line_width(rw) <= one_line_budget {
-                ::std::mem::swap(last_child, rw);
-                return true;
-            }
-        }
-    }
-    false
+fn repeat_try(try_count: usize) -> String {
+    iter::repeat("?").take(try_count).collect::<String>()
 }
 
-pub fn rewrite_try(expr: &ast::Expr,
-                   try_count: usize,
-                   context: &RewriteContext,
-                   shape: Shape)
-                   -> Option<String> {
-    let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count))));
-    Some(format!("{}{}",
-                 sub_expr,
-                 iter::repeat("?").take(try_count).collect::<String>()))
+fn rewrite_try(
+    expr: &ast::Expr,
+    try_count: usize,
+    context: &RewriteContext,
+    shape: Shape,
+) -> Option<String> {
+    let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?;
+    Some(format!("{}{}", sub_expr, repeat_try(try_count)))
 }
 
-fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String {
+fn join_rewrites(rewrites: &[String], connector: &str) -> String {
     let mut rewrite_iter = rewrites.iter();
     let mut result = rewrite_iter.next().unwrap().clone();
-    let mut subexpr_iter = subexps.iter().rev();
-    subexpr_iter.next();
 
-    for (rewrite, expr) in rewrite_iter.zip(subexpr_iter) {
-        match expr.node {
-            ast::ExprKind::Try(_) => (),
-            _ => result.push_str(connector),
-        };
+    for rewrite in rewrite_iter {
+        if rewrite != "?" {
+            result.push_str(connector);
+        }
         result.push_str(&rewrite[..]);
     }
 
@@ -340,8 +338,8 @@ fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) ->
 // parens, braces, and brackets in its idiomatic formatting.
 fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool {
     match expr.node {
-        ast::ExprKind::Call(..) => {
-            context.config.fn_call_style() == IndentStyle::Block && repr.contains('\n')
+        ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => {
+            context.use_block_indent() && repr.contains('\n')
         }
         ast::ExprKind::Struct(..) |
         ast::ExprKind::While(..) |
@@ -376,37 +374,9 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr,
 fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape {
     match context.config.chain_indent() {
         IndentStyle::Visual => shape.visual_indent(0),
-        IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
-    }
-}
-
-fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
-                                     last: &mut String,
-                                     almost_total: usize,
-                                     total_span: Span,
-                                     context: &RewriteContext,
-                                     shape: Shape)
-                                     -> bool {
-    if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind {
-        let shape = match shape.shrink_left(almost_total) {
-            Some(b) => b,
-            None => return false,
-        };
-        let mut last_rewrite = rewrite_method_call(method_name.node,
-                                                   types,
-                                                   expressions,
-                                                   total_span,
-                                                   context,
-                                                   shape);
-
-        if let Some(ref mut s) = last_rewrite {
-            ::std::mem::swap(s, last);
-            true
-        } else {
-            false
-        }
-    } else {
-        unreachable!();
+        IndentStyle::Block => shape
+            .block_indent(context.config.tab_spaces())
+            .with_max_width(context.config),
     }
 }
 
@@ -414,7 +384,7 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
 // is a try! macro, we'll convert it to shorthand when the option is set.
 fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option<ast::Expr> {
     match expr.node {
-        ast::ExprKind::MethodCall(_, _, ref expressions) => {
+        ast::ExprKind::MethodCall(_, ref expressions) => {
             Some(convert_try(&expressions[0], context))
         }
         ast::ExprKind::TupField(ref subexpr, _) |
@@ -439,11 +409,12 @@ fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr {
 
 // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite
 // `.c`.
-fn rewrite_chain_subexpr(expr: &ast::Expr,
-                         span: Span,
-                         context: &RewriteContext,
-                         shape: Shape)
-                         -> Option<String> {
+fn rewrite_chain_subexpr(
+    expr: &ast::Expr,
+    span: Span,
+    context: &RewriteContext,
+    shape: Shape,
+) -> Option<String> {
     let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width {
         Some(expr_str)
     } else {
@@ -451,11 +422,24 @@ fn rewrite_chain_subexpr(expr: &ast::Expr,
     };
 
     match expr.node {
-        ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => {
-            rewrite_method_call(method_name.node, types, expressions, span, context, shape)
+        ast::ExprKind::MethodCall(ref segment, ref expressions) => {
+            let types = match segment.parameters {
+                Some(ref params) => match **params {
+                    ast::PathParameters::AngleBracketed(ref data) => &data.types[..],
+                    _ => &[],
+                },
+                _ => &[],
+            };
+            rewrite_method_call(segment.identifier, types, expressions, span, context, shape)
         }
         ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)),
-        ast::ExprKind::TupField(_, ref field) => rewrite_element(format!(".{}", field.node)),
+        ast::ExprKind::TupField(ref expr, ref field) => {
+            let space = match expr.node {
+                ast::ExprKind::TupField(..) => " ",
+                _ => "",
+            };
+            rewrite_element(format!("{}.{}", space, field.node))
+        }
         ast::ExprKind::Try(_) => rewrite_element(String::from("?")),
         _ => unreachable!(),
     }
@@ -469,30 +453,40 @@ fn is_continuable(expr: &ast::Expr) -> bool {
     }
 }
 
-fn rewrite_method_call(method_name: ast::Ident,
-                       types: &[ptr::P<ast::Ty>],
-                       args: &[ptr::P<ast::Expr>],
-                       span: Span,
-                       context: &RewriteContext,
-                       shape: Shape)
-                       -> Option<String> {
+fn is_try(expr: &ast::Expr) -> bool {
+    match expr.node {
+        ast::ExprKind::Try(..) => true,
+        _ => false,
+    }
+}
+
+fn rewrite_method_call(
+    method_name: ast::Ident,
+    types: &[ptr::P<ast::Ty>],
+    args: &[ptr::P<ast::Expr>],
+    span: Span,
+    context: &RewriteContext,
+    shape: Shape,
+) -> Option<String> {
     let (lo, type_str) = if types.is_empty() {
-        (args[0].span.hi, String::new())
+        (args[0].span.hi(), String::new())
     } else {
-        let type_list: Vec<_> =
-            try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect());
+        let type_list = types
+            .iter()
+            .map(|ty| ty.rewrite(context, shape))
+            .collect::<Option<Vec<_>>>()?;
 
-        let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 {
+        let type_str = if context.config.spaces_within_angle_brackets() && !type_list.is_empty() {
             format!("::< {} >", type_list.join(", "))
         } else {
             format!("::<{}>", type_list.join(", "))
         };
 
-        (types.last().unwrap().span.hi, type_str)
+        (types.last().unwrap().span.hi(), type_str)
     };
 
     let callee_str = format!(".{}{}", method_name, type_str);
-    let span = mk_sp(lo, span.hi);
+    let span = mk_sp(lo, span.hi());
 
     rewrite_call(context, &callee_str, &args[1..], span, shape)
 }