From f1d29ff58011235bd8edd1fa55578ff1bc9c7dda Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:29:01 +0900 Subject: [PATCH 1/8] Update tests for braces on trait Test that the opening brace of trait with long name or bounds with multiple lines will be put on the next line. --- tests/source/issue-2506.rs | 2 +- tests/target/impls.rs | 6 ++++-- tests/target/issue-2506.rs | 4 ++-- tests/target/trait.rs | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/source/issue-2506.rs b/tests/source/issue-2506.rs index fd0ecc9c661e..94a927580f6a 100644 --- a/tests/source/issue-2506.rs +++ b/tests/source/issue-2506.rs @@ -7,7 +7,7 @@ fn main() { fn f1(a: Box) {} // checks if line wrap works correctly - trait Very_______________________Long__________________Name____________________Trait { + trait Very_______________________Long__________________Name_______________________________Trait { fn method(&self) -> u64; } diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 0bc28acf7eaa..0e209328972b 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -183,7 +183,8 @@ pub trait Number + BitAnd + BitOr + BitAndAssign - + BitOrAssign { + + BitOrAssign +{ // test fn zero() -> Self; } @@ -201,7 +202,8 @@ pub trait SomeTrait + Display + Write + Read - + FromStr { + + FromStr +{ // comment } diff --git a/tests/target/issue-2506.rs b/tests/target/issue-2506.rs index ee2debee9fb9..1e1971db85f6 100644 --- a/tests/target/issue-2506.rs +++ b/tests/target/issue-2506.rs @@ -7,8 +7,8 @@ fn main() { fn f1(a: Box) {} // checks if line wrap works correctly - trait Very_______________________Long__________________Name____________________Trait - { + trait Very_______________________Long__________________Name_______________________________Trait + { fn method(&self) -> u64; } diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 133e8babedb9..f3b909793689 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -106,7 +106,8 @@ trait MyTrait< BBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCC, DDDDDDDDDDDDDDDDDDDD, -> { +> +{ fn foo() {} } From c7d70917725ce0fe9e9c40c0438819b0482c7ba6 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:30:47 +0900 Subject: [PATCH 2/8] Update tests for traits with long bounds The colon should be next to the ident instead of on the next line. --- tests/target/impls.rs | 8 ++++---- tests/target/trait.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 0e209328972b..2175b5d7bd9d 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -174,8 +174,8 @@ impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { } // #1168 -pub trait Number - : Copy +pub trait Number: + Copy + Eq + Not + Shl @@ -190,8 +190,8 @@ pub trait Number } // #1642 -pub trait SomeTrait - : Clone +pub trait SomeTrait: + Clone + Eq + PartialEq + Ord diff --git a/tests/target/trait.rs b/tests/target/trait.rs index f3b909793689..fa54b1d2df1e 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -65,8 +65,8 @@ where { } -trait FooBar - : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +trait FooBar: + Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar, { From 8f7a90fbefd68a919cd6f4214829208798583199 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:35:53 +0900 Subject: [PATCH 3/8] Add rewrite_assign_rhs_with It is like `rewrite_assign_rhs` but lets us force to put the rhs on the next line if it uses multiple lines. This lets us avoid duplicating logic for choosing whether to put stuff on the same line or the next line. --- src/expr.rs | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 6e740f43f828..0e6b8f1bc1e3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1698,7 +1698,8 @@ fn rewrite_match_body( ); match (orig_body, next_line_body) { (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line || prefer_next_line(orig_str, next_line_str) => + if forbid_same_line + || prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { combine_next_line_body(next_line_str) } @@ -2514,6 +2515,15 @@ fn rewrite_assignment( rewrite_assign_rhs(context, lhs_str, rhs, shape) } +/// Controls where to put the rhs. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum RhsTactics { + /// Use heuristics. + Default, + /// Put the rhs on the next line if it uses multiple line. + ForceNextLine, +} + // The left hand side must contain everything up to, and including, the // assignment operator. pub fn rewrite_assign_rhs, R: Rewrite>( @@ -2521,6 +2531,16 @@ pub fn rewrite_assign_rhs, R: Rewrite>( lhs: S, ex: &R, shape: Shape, +) -> Option { + rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) +} + +pub fn rewrite_assign_rhs_with, R: Rewrite>( + context: &RewriteContext, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, ) -> Option { let lhs = lhs.into(); let last_line_width = last_line_width(&lhs) @@ -2536,15 +2556,22 @@ pub fn rewrite_assign_rhs, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); - let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; + let rhs = choose_rhs( + context, + ex, + orig_shape, + ex.rewrite(context, orig_shape), + rhs_tactics, + )?; Some(lhs + &rhs) } -pub fn choose_rhs( +fn choose_rhs( context: &RewriteContext, expr: &R, shape: Shape, orig_rhs: Option, + rhs_tactics: RhsTactics, ) -> Option { match orig_rhs { Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { @@ -2566,7 +2593,9 @@ pub fn choose_rhs( { Some(format!(" {}", orig_rhs)) } - (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { + (Some(ref orig_rhs), Some(ref new_rhs)) + if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => + { Some(format!("{}{}", new_indent_str, new_rhs)) } (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), @@ -2577,8 +2606,9 @@ pub fn choose_rhs( } } -fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 +fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { + rhs_tactics == RhsTactics::ForceNextLine || !next_line_rhs.contains('\n') + || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } fn rewrite_expr_addrof( From f56039c7e584bb5b9b5453056a3f4c5197615629 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:54:13 +0900 Subject: [PATCH 4/8] Use rewrite_assign_rhs for rewriting bounds --- src/items.rs | 59 ++++++++---------------- src/types.rs | 126 ++++++++++++++++++++++++++------------------------- 2 files changed, 84 insertions(+), 101 deletions(-) diff --git a/src/items.rs b/src/items.rs index d3286864ce7d..2484756fc56a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,13 +23,14 @@ use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_assign_rhs_with, ExprType, RhsTactics}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use overflow; use shape::{Indent, Shape}; use spanned::Spanned; -use types::join_bounds; +use types::TraitTyParamBounds; use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, @@ -919,20 +920,19 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) return None; } } - let trait_bound_str = rewrite_trait_bounds( - context, - type_param_bounds, - 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 - if offset.width() + last_line_width(&result) + trait_bound_str.len() - > context.config.comment_width() - { - let trait_indent = offset.block_only().block_indent(context.config); - result.push_str(&trait_indent.to_string_with_newline(context.config)); + if !type_param_bounds.is_empty() { + let shape = Shape { + indent: shape.indent.block_unindent(context.config), + ..shape + }; + result = rewrite_assign_rhs_with( + context, + result + ":", + &TraitTyParamBounds::new(type_param_bounds), + shape, + RhsTactics::ForceNextLine, + )?; } - result.push_str(&trait_bound_str); let where_density = if context.config.indent_style() == IndentStyle::Block && result.is_empty() { @@ -1585,16 +1585,12 @@ pub fn rewrite_associated_type( let prefix = format!("type {}", ident); let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - if !bounds.is_empty() { - format!(": {}", join_bounds(context, shape, &bound_str)) - } else { + if bounds.is_empty() { String::new() + } else { + // 2 = ": ".len() + let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; + bounds.rewrite(context, shape).map(|s| format!(": {}", s))? } } else { String::new() @@ -2329,21 +2325,6 @@ pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) } } -fn rewrite_trait_bounds( - context: &RewriteContext, - bounds: &[ast::TyParamBound], - shape: Shape, -) -> Option { - if bounds.is_empty() { - return Some(String::new()); - } - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - Some(format!(": {}", join_bounds(context, shape, &bound_str))) -} - fn rewrite_where_clause_rfc_style( context: &RewriteContext, where_clause: &ast::WhereClause, diff --git a/src/types.rs b/src/types.rs index ac7990b9c0b0..80ff8ce498ae 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,7 +18,8 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr}; +use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, + PairParts, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -431,64 +432,35 @@ impl Rewrite for ast::WherePredicate { .. }) => { let type_str = bounded_ty.rewrite(context, shape)?; - - let colon = type_bound_colon(context); - - if let Some(lifetime_str) = + let colon = type_bound_colon(context).trim_right(); + let lhs = if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, bound_generic_params) { - // 6 = "for<> ".len() - let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = shape.offset_left(used_width)?; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let bounds_str = join_bounds(context, ty_shape, &bounds); - if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { - format!( - "for< {} > {}{}{}", - lifetime_str, type_str, colon, bounds_str - ) + format!("for< {} > {}{}", lifetime_str, type_str, colon) } else { - format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) + format!("for<{}> {}{}", lifetime_str, type_str, colon) } } else { - let used_width = type_str.len() + colon.len(); - let ty_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.block_left(used_width)?, - IndentStyle::Block => shape, - }; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let overhead = type_str.len() + colon.len(); - let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); + format!("{}{}", type_str, colon) + }; - format!("{}{}{}", type_str, colon, bounds_str) - } + rewrite_assign_rhs(context, lhs, bounds, shape)? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, .. - }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, + }) => rewrite_bounded_lifetime(lifetime, bounds, context, shape)?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape)?; - // 3 = " = ".len() - let used_width = 3 + lhs_ty_str.len(); - let budget = shape.width.checked_sub(used_width)?; - let rhs_ty_str = - rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; - format!("{} = {}", lhs_ty_str, rhs_ty_str) + let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, shape)? } }; @@ -498,26 +470,23 @@ impl Rewrite for ast::WherePredicate { impl Rewrite for ast::LifetimeDef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) + rewrite_bounded_lifetime(&self.lifetime, &self.bounds, context, shape) } } -fn rewrite_bounded_lifetime<'b, I>( +fn rewrite_bounded_lifetime( lt: &ast::Lifetime, - bounds: I, + bounds: &[ast::Lifetime], context: &RewriteContext, shape: Shape, -) -> Option -where - I: ExactSizeIterator, -{ +) -> Option { let result = lt.rewrite(context, shape)?; if bounds.len() == 0 { Some(result) } else { let appendix = bounds - .into_iter() + .iter() .map(|b| b.rewrite(context, shape)) .collect::>>()?; let colon = type_bound_colon(context); @@ -526,7 +495,7 @@ where "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, &appendix) + join_bounds(context, shape.sub_width(overhead)?, bounds, &appendix, true)? ); Some(result) } @@ -552,12 +521,28 @@ impl Rewrite for ast::Lifetime { } } +/// A simple wrapper over type param bounds in trait. +#[derive(new)] +pub struct TraitTyParamBounds<'a> { + inner: &'a ast::TyParamBounds, +} + +impl<'a> Rewrite for TraitTyParamBounds<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let strs = self.inner + .iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + join_bounds(context, shape, self.inner, &strs, false) + } +} + impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let strs = self.iter() .map(|b| b.rewrite(context, shape)) .collect::>>()?; - Some(join_bounds(context, shape, &strs)) + join_bounds(context, shape, self, &strs, true) } } @@ -572,11 +557,7 @@ impl Rewrite for ast::TyParam { result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); - let strs = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - result.push_str(&join_bounds(context, shape, &strs)); + result.push_str(&self.bounds.rewrite(context, shape)?) } if let Some(ref def) = self.default { let eq_str = match context.config.type_punctuation_density() { @@ -794,20 +775,41 @@ fn rewrite_bare_fn( Some(result) } -pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { +fn join_bounds( + context: &RewriteContext, + shape: Shape, + items: &[T], + type_strs: &[String], + need_indent: bool, +) -> Option +where + T: Rewrite, +{ // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; let result = type_strs.join(joiner); - if result.contains('\n') || result.len() > shape.width { - let joiner_indent = shape.indent.block_indent(context.config); - let joiner = format!("{}+ ", joiner_indent.to_string_with_newline(context.config)); - type_strs.join(&joiner) - } else { - result + if items.len() == 1 || (!result.contains('\n') && result.len() <= shape.width) { + return Some(result); } + + // We need to use multiple lines. + let (type_strs, offset) = if need_indent { + // Rewrite with additional indentation. + let nested_shape = shape.block_indent(context.config.tab_spaces()); + let type_strs = items + .iter() + .map(|item| item.rewrite(context, nested_shape)) + .collect::>>()?; + (type_strs, nested_shape.indent) + } else { + (type_strs.to_vec(), shape.indent) + }; + + let joiner = format!("{}+ ", offset.to_string_with_newline(context.config)); + Some(type_strs.join(&joiner)) } pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { From b077297179b41420701e36f55b507bd2299811b5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:55:30 +0900 Subject: [PATCH 5/8] Modify the placement of the opening brace of trait Put the opening brace on the next line if 1. putting it one the current line exceeds max width. 2. trait bounds uses multiple lines. --- src/items.rs | 74 +++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/items.rs b/src/items.rs index 2484756fc56a..1d02ba653ce6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -934,45 +934,45 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) )?; } - let where_density = - if context.config.indent_style() == IndentStyle::Block && result.is_empty() { + // Rewrite where clause. + if !generics.where_clause.predicates.is_empty() { + let where_density = if context.config.indent_style() == IndentStyle::Block { Density::Compressed } else { Density::Tall }; - let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if type_param_bounds.is_empty() { - generics.where_clause.span.lo() + let where_budget = context.budget(last_line_width(&result)); + let pos_before_where = if type_param_bounds.is_empty() { + generics.where_clause.span.lo() + } else { + type_param_bounds[type_param_bounds.len() - 1].span().hi() + }; + let option = WhereClauseOption::snuggled(&generics_str); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + where_density, + "{", + None, + pos_before_where, + option, + false, + )?; + // If the where clause cannot fit on the same line, + // put the where clause on a new line + if !where_clause_str.contains('\n') + && last_line_width(&result) + where_clause_str.len() + offset.width() + > context.config.comment_width() + { + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string_with_newline(context.config)); + } + result.push_str(&where_clause_str); } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi() - }; - let option = WhereClauseOption::snuggled(&generics_str); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - where_density, - "{", - None, - pos_before_where, - option, - false, - )?; - // If the where clause cannot fit on the same line, - // put the where clause on a new line - if !where_clause_str.contains('\n') - && last_line_width(&result) + where_clause_str.len() + offset.width() - > context.config.comment_width() - { - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string_with_newline(context.config)); - } - result.push_str(&where_clause_str); - - if generics.where_clause.predicates.is_empty() { let item_snippet = context.snippet(item.span); if let Some(lo) = item_snippet.chars().position(|c| c == '/') { // 1 = `{` @@ -995,7 +995,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } match context.config.brace_style() { - _ if last_line_contains_single_line_comment(&result) => { + _ if last_line_contains_single_line_comment(&result) + || last_line_width(&result) + 2 > context.budget(offset.width()) => + { result.push_str(&offset.to_string_with_newline(context.config)); } BraceStyle::AlwaysNextLine => { @@ -1003,8 +1005,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() - && (!trait_items.is_empty() || result.contains('\n')) + if result.contains('\n') + || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty()) { result.push_str(&offset.to_string_with_newline(context.config)); } else { From 7917d6f94acff2cd666b95d4e6c7b7acb6442d2c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:57:31 +0900 Subject: [PATCH 6/8] Update tests This is an unintentional side effect of this PR. Nonetheless the diff looks harmless to me, and it is only relevant when `indent_style = Visual`. So I think this is ok. --- tests/target/where-clause.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs index def18a0c11a8..eb2f8d5e6e81 100644 --- a/tests/target/where-clause.rs +++ b/tests/target/where-clause.rs @@ -81,17 +81,17 @@ struct AlwaysOnNextLine pub trait SomeTrait where T: Something - + Sync - + Send - + Display - + Debug - + Copy - + Hash - + Debug - + Display - + Write - + Read - + FromStr + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read + + FromStr { } From ccd134ed75f8c7f039040e9bdf60b8d904ff4fbc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 15:11:49 +0900 Subject: [PATCH 7/8] Add a test for #2497 Closes #2497. --- src/items.rs | 4 ---- tests/source/where-clause-rfc.rs | 17 +++++++++++++++++ tests/target/where-clause-rfc.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/items.rs b/src/items.rs index 1d02ba653ce6..b639697194b7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -921,10 +921,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } if !type_param_bounds.is_empty() { - let shape = Shape { - indent: shape.indent.block_unindent(context.config), - ..shape - }; result = rewrite_assign_rhs_with( context, result + ":", diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs index e41e9a6cea1c..d915fccf1a0f 100644 --- a/tests/source/where-clause-rfc.rs +++ b/tests/source/where-clause-rfc.rs @@ -56,3 +56,20 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // ... } } + +// #2497 +fn handle_update<'a, Tab, Conn, R, C>(executor: &Executor>>, change_set: &'a C) -> ExecutionResult +where &'a C: Identifiable + AsChangeset + HasTable, + <&'a C as AsChangeset>::Changeset: QueryFragment, + Tab: Table + HasTable
, + Tab::PrimaryKey: EqAll<<&'a C as Identifiable>::Id>, + Tab::FromClause: QueryFragment, + Tab: FindDsl<<&'a C as Identifiable>::Id>, + Find::Id>: IntoUpdateTarget
, + ::Id> as IntoUpdateTarget>::WhereClause: QueryFragment, + Tab::Query: FilterDsl<::Id>>::Output>, + Filter::Id>>::Output>: LimitDsl, + Limit::Id>>::Output>>: QueryDsl + BoxedDsl< 'a, Conn::Backend, Output = BoxedSelectStatement<'a, R::SqlType, Tab, Conn::Backend>>, + R: LoadingHandler + GraphQLType, { + unimplemented!() +} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index 1e83d5b3abc4..a41d82c8e417 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -126,3 +126,33 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // ... } } + +// #2497 +fn handle_update<'a, Tab, Conn, R, C>( + executor: &Executor>>, + change_set: &'a C, +) -> ExecutionResult +where + &'a C: Identifiable + AsChangeset + HasTable
, + <&'a C as AsChangeset>::Changeset: QueryFragment, + Tab: Table + HasTable
, + Tab::PrimaryKey: EqAll<<&'a C as Identifiable>::Id>, + Tab::FromClause: QueryFragment, + Tab: FindDsl<<&'a C as Identifiable>::Id>, + Find::Id>: IntoUpdateTarget
, + ::Id> as IntoUpdateTarget>::WhereClause: + QueryFragment, + Tab::Query: FilterDsl<::Id>>::Output>, + Filter::Id>>::Output>: LimitDsl, + Limit::Id>>::Output>>: + QueryDsl + + BoxedDsl< + 'a, + Conn::Backend, + Output = BoxedSelectStatement<'a, R::SqlType, Tab, Conn::Backend>, + >, + R: LoadingHandler + + GraphQLType, +{ + unimplemented!() +} From 182b46e0ed29621f4cd29f39b8dd82f5a9b63e3f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 15:23:42 +0900 Subject: [PATCH 8/8] Simplify join_bounds() --- src/types.rs | 28 ++++++++++------------------ tests/target/trait.rs | 3 +-- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/types.rs b/src/types.rs index 80ff8ce498ae..676095ff4ce4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,8 +18,8 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, - PairParts, ToExpr}; +use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, + ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -485,17 +485,13 @@ fn rewrite_bounded_lifetime( if bounds.len() == 0 { Some(result) } else { - let appendix = bounds - .iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); let result = format!( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, &appendix, true)? + join_bounds(context, shape.sub_width(overhead)?, bounds, true)? ); Some(result) } @@ -529,20 +525,13 @@ pub struct TraitTyParamBounds<'a> { impl<'a> Rewrite for TraitTyParamBounds<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.inner - .iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - join_bounds(context, shape, self.inner, &strs, false) + join_bounds(context, shape, self.inner, false) } } impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - join_bounds(context, shape, self, &strs, true) + join_bounds(context, shape, self, true) } } @@ -779,7 +768,6 @@ fn join_bounds( context: &RewriteContext, shape: Shape, items: &[T], - type_strs: &[String], need_indent: bool, ) -> Option where @@ -790,6 +778,10 @@ where TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; + let type_strs = items + .iter() + .map(|item| item.rewrite(context, shape)) + .collect::>>()?; let result = type_strs.join(joiner); if items.len() == 1 || (!result.contains('\n') && result.len() <= shape.width) { return Some(result); @@ -805,7 +797,7 @@ where .collect::>>()?; (type_strs, nested_shape.indent) } else { - (type_strs.to_vec(), shape.indent) + (type_strs, shape.indent) }; let joiner = format!("{}+ ", offset.to_string_with_newline(context.config)); diff --git a/tests/target/trait.rs b/tests/target/trait.rs index fa54b1d2df1e..d1ee43f4e3f1 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -65,8 +65,7 @@ where { } -trait FooBar: - Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +trait FooBar: Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar, {