diff --git a/src/items.rs b/src/items.rs index 40d57ac45d7a..09d866ccf8da 100644 --- a/src/items.rs +++ b/src/items.rs @@ -705,16 +705,17 @@ fn format_impl_ref_and_type( Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, }; - let shape = generics_shape_from_config( + let shape = try_opt!(generics_shape_from_config( context.config, Shape::indented(offset + last_line_width(&result), context.config), 0, - ); + )); + let one_line_budget = try_opt!(shape.width.checked_sub(last_line_width(&result) + 2)); let generics_str = try_opt!(rewrite_generics_inner( context, generics, shape, - shape.width, + one_line_budget, mk_sp(lo, hi), )); @@ -927,7 +928,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let trait_bound_str = try_opt!(rewrite_trait_bounds( context, type_param_bounds, - Shape::legacy(context.config.max_width(), offset), + Shape::indented(offset, context.config), )); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line @@ -1591,7 +1592,7 @@ pub fn rewrite_associated_type( let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let shape = Shape::legacy(context.config.max_width(), indent); + let shape = Shape::indented(indent, context.config); let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!( bounds @@ -1900,7 +1901,8 @@ fn rewrite_fn_base( if context.config.fn_args_layout() == IndentStyle::Block { arg_indent = indent.block_indent(context.config); - multi_line_budget = context.config.max_width() - arg_indent.width(); + // 1 = "," + multi_line_budget = context.config.max_width() - (arg_indent.width() + 1); } debug!( @@ -2386,9 +2388,11 @@ fn rewrite_generics( shape: Shape, span: Span, ) -> Option { - let shape = generics_shape_from_config(context.config, shape, 0); - rewrite_generics_inner(context, generics, shape, shape.width, span) - .or_else(|| rewrite_generics_inner(context, generics, shape, 0, span)) + let g_shape = try_opt!(generics_shape_from_config(context.config, shape, 0)); + let one_line_width = try_opt!(shape.width.checked_sub(2)); + rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| { + rewrite_generics_inner(context, generics, g_shape, 0, span) + }) } fn rewrite_generics_inner( @@ -2435,14 +2439,17 @@ fn rewrite_generics_inner( format_generics_item_list(context, items, shape, one_line_width) } -pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Shape { - Shape { - // 2 = `<>` - width: shape.width.checked_sub(offset + 2).unwrap_or(0), - ..match config.generics_indent() { - IndentStyle::Visual => shape.visual_indent(1 + offset), - IndentStyle::Block => shape.block().block_indent(config.tab_spaces()), - } +pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { + match config.generics_indent() { + IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), + IndentStyle::Block => { + // 1 = "," + shape + .block() + .block_indent(config.tab_spaces()) + .with_max_width(config) + .sub_width(1) + } } } @@ -2531,7 +2538,7 @@ fn rewrite_where_clause_rfc_style( snuggle: bool, span_end: Option, ) -> Option { - let block_shape = shape.block(); + let block_shape = shape.block().with_max_width(context.config); let starting_newline = if snuggle { " ".to_owned() @@ -2553,7 +2560,7 @@ fn rewrite_where_clause_rfc_style( terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, shape), + |pred| pred.rewrite(context, block_shape), span_start, span_end, ); diff --git a/src/lists.rs b/src/lists.rs index d176ef01f9b5..1d3be8045e23 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -68,18 +68,6 @@ pub struct ListFormatting<'a> { pub config: &'a Config, } -pub fn format_fn_args(items: I, shape: Shape, config: &Config) -> Option -where - I: Iterator, -{ - list_helper( - items, - shape, - config, - ListTactic::LimitedHorizontalVertical(config.fn_call_width()), - ) -} - pub fn format_item_list(items: I, shape: Shape, config: &Config) -> Option where I: Iterator, diff --git a/src/types.rs b/src/types.rs index 39b35de20b21..8ba0d64de9e3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -20,11 +20,12 @@ use syntax::symbol::keywords; use {Shape, Spanned}; use codemap::SpanUtils; use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{itemize_list, format_fn_args}; +use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, + definitive_tactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; -use config::{Style, TypeDensity}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple, wrap_args_with_parens}; +use config::{IndentStyle, Style, TypeDensity}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -225,8 +226,12 @@ fn rewrite_segment( "" }; - let generics_shape = - generics_shape_from_config(context.config, shape, separator.len()); + let generics_shape = try_opt!(generics_shape_from_config( + context.config, + shape, + separator.len(), + )); + let one_line_width = try_opt!(shape.width.checked_sub(separator.len() + 2)); let items = itemize_list( context.codemap, param_list.into_iter(), @@ -241,7 +246,7 @@ fn rewrite_segment( context, items, generics_shape, - generics_shape.width, + one_line_width, )); // Update position of last bracket. @@ -306,7 +311,16 @@ where // 2 for () let budget = try_opt!(shape.width.checked_sub(2)); // 1 for ( - let offset = shape.indent + 1; + let offset = match context.config.fn_args_layout() { + IndentStyle::Block => { + shape + .block() + .block_indent(context.config.tab_spaces()) + .indent + } + IndentStyle::Visual => shape.indent + 1, + }; + let list_shape = Shape::legacy(budget, offset); let list_lo = context.codemap.span_after(span, "("); let items = itemize_list( context.codemap, @@ -325,39 +339,64 @@ where ArgumentKind::Variadic(start) => start + BytePos(3), }, |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, Shape::legacy(budget, offset)), + ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), ArgumentKind::Variadic(_) => Some("...".to_owned()), }, list_lo, span.hi, ); - let list_str = try_opt!(format_fn_args( - items, - Shape::legacy(budget, offset), - context.config, - )); + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic(&*item_vec, ListTactic::HorizontalVertical, budget); + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + shape: list_shape, + ends_with_newline: false, + config: context.config, + }; + + let list_str = try_opt!(write_list(&item_vec, &fmt)); + + let ty_shape = match context.config.fn_args_layout() { + IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), + IndentStyle::Visual => try_opt!(shape.block_left(4)), + }; let output = match *output { FunctionRetTy::Ty(ref ty) => { - let budget = try_opt!(shape.width.checked_sub(4)); - let type_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, offset + 4))); + let type_str = try_opt!(ty.rewrite(context, ty_shape)); format!(" -> {}", type_str) } FunctionRetTy::Default(..) => String::new(), }; - let infix = if !output.is_empty() && output.len() + list_str.len() > shape.width { - format!("\n{}", (offset - 1).to_string(context.config)) + let shape = try_opt!(shape.sub_width(output.len())); + let extendable = !list_str.contains('\n') || list_str.is_empty(); + let args = wrap_args_with_parens( + context, + &list_str, + extendable, + shape, + Shape::indented(offset, context.config), + ); + if last_line_width(&args) + output.len() > shape.width { + Some(format!( + "{}\n{}{}", + args, + offset.to_string(context.config), + output.trim_left() + )) } else { - String::new() - }; + Some(format!("{}{}", args, output)) + } - Some(if context.config.spaces_within_parens() { - format!("( {} ){}{}", list_str, infix, output) - } else { - format!("({}){}{}", list_str, infix, output) - }) } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -423,7 +462,9 @@ impl Rewrite for ast::WherePredicate { .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) .collect() ); - let bounds_str = join_bounds(context, ty_shape, &bounds); + let overhead = type_str.len() + colon.len(); + let bounds_str = + join_bounds(context, try_opt!(ty_shape.sub_width(overhead)), &bounds); format!("{}{}{}", type_str, colon, bounds_str) } @@ -762,8 +803,7 @@ fn rewrite_bare_fn( result.push_str("fn"); - let budget = try_opt!(shape.width.checked_sub(result.len())); - let indent = shape.indent + result.len(); + let func_ty_shape = try_opt!(shape.offset_left(result.len())); let rewrite = try_opt!(format_function_type( bare_fn.decl.inputs.iter(), @@ -771,7 +811,7 @@ fn rewrite_bare_fn( bare_fn.decl.variadic, span, context, - Shape::legacy(budget, indent), + func_ty_shape, )); result.push_str(&rewrite); diff --git a/tests/source/big-impl-rfc.rs b/tests/source/big-impl-rfc.rs index 167f654cc439..2f04ee1ef92d 100644 --- a/tests/source/big-impl-rfc.rs +++ b/tests/source/big-impl-rfc.rs @@ -112,3 +112,17 @@ impl< > { fn foo() {} } + +// #1689 +impl SubSelectDirect + where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api< + 't, + Stream>, + >) + -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs index 7c0b500c7538..58c807f4029e 100644 --- a/tests/source/type_alias.rs +++ b/tests/source/type_alias.rs @@ -28,3 +28,7 @@ pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + E pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = super::operators::Between, AsExpr>>; +pub type NotBetween = super::operators::NotBetween, AsExpr>>; diff --git a/tests/target/big-impl-rfc.rs b/tests/target/big-impl-rfc.rs index 108968faaed7..da5ab03fd5eb 100644 --- a/tests/target/big-impl-rfc.rs +++ b/tests/target/big-impl-rfc.rs @@ -75,3 +75,14 @@ impl< > { fn foo() {} } + +// #1689 +impl SubSelectDirect +where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api<'t, Stream>>) + -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/tests/target/extern_not_explicit.rs b/tests/target/extern_not_explicit.rs index b0f64c4f1cf5..b55b64d05b34 100644 --- a/tests/target/extern_not_explicit.rs +++ b/tests/target/extern_not_explicit.rs @@ -6,10 +6,13 @@ extern { extern fn sup() {} -type funky_func = extern fn(unsafe extern "rust-call" fn(*const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal) - -> u8); +type funky_func = extern fn( + unsafe extern "rust-call" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, +); diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 102c1449627d..76776672ca8c 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -10,7 +10,7 @@ fn simple( key: &[u8], upd: Box< Fn(Option<&memcache::Item>) - -> (memcache::Status, Result>), + -> (memcache::Status, Result>), >, ) -> MapResult { } @@ -34,15 +34,16 @@ fn weird_comment( fn generic(arg: T) -> &SomeType where - T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType, + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, /* last comment */ + ) -> &SomeType, { arg(a, b, c, d, e) } @@ -68,13 +69,14 @@ unsafe fn generic_call( argc: libc::c_uint, vp: *mut JSVal, is_lenient: bool, - call: unsafe extern "C" fn(*const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal) - -> u8, + call: unsafe extern "C" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, ) { let f: fn(_, _) -> _ = panic!(); } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index c8102fe3b540..8b581e835394 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -102,8 +102,7 @@ fn foo(a: i32) -> i32 { fn ______________________baz( a: i32, ) -> *mut ::std::option::Option< - extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) - -> (), + extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) -> (), > { } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 68919b1039c8..c2f8d2522370 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -59,15 +59,16 @@ fn main() { fn generic(arg: T) -> &SomeType where - T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType, + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, /* last comment */ + ) -> &SomeType, { arg(a, b, c, d, e) } diff --git a/tests/target/type.rs b/tests/target/type.rs index 85abf1b6fc2c..80855ee5732a 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -13,16 +13,20 @@ fn types() { struct F { f: extern "C" fn(x: u8, ... /* comment */), - g: 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 */), + i: extern "C" fn( + x: u8, + // comment 4 + y: String, // comment 3 + z: Foo, + // comment + ... /* comment 2 */ + ), } fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 58ca5112346b..cac1ac466cd5 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -26,8 +26,9 @@ pub type LongGenericListTest< pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = - Vec; +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec< + Test, +>; pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; @@ -61,6 +62,14 @@ pub type Exactly100CharstoEqualWhereTest where pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; -type RegisterPlugin = unsafe fn(pt: *const c_char, - plugin: *mut c_void, - data: *mut CallbackData); +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = super::operators::Between< + Lhs, + super::operators::And, AsExpr>, +>; +pub type NotBetween = super::operators::NotBetween< + Lhs, + super::operators::And, AsExpr>, +>;