diff --git a/src/formatting/items.rs b/src/formatting/items.rs index 854660c636c..ca09d063224 100644 --- a/src/formatting/items.rs +++ b/src/formatting/items.rs @@ -34,6 +34,7 @@ use crate::formatting::{ vertical::rewrite_with_alignment, visitor::FmtVisitor, }; +use std::ops::Add; const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { kind: ast::VisibilityKind::Inherited, @@ -2528,34 +2529,6 @@ fn rewrite_fn_base( } else { result.push_str(&ret_str); } - - if where_clause.predicates.is_empty() { - // Comment between return type and the end of the decl. - // Even if there are no predicates in the where clause, the "where" kw may be present, - // so start the snippet after it. - let snippet_lo = where_clause.span.hi(); - let snippet_hi = span.hi(); - let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); - // Try to preserve the layout of the original snippet. - let original_starts_with_newline = snippet - .find(|c| c != ' ') - .map_or(false, |i| starts_with_newline(&snippet[i..])); - let original_ends_with_newline = snippet - .rfind(|c| c != ' ') - .map_or(false, |i| snippet[i..].ends_with('\n')); - let snippet = snippet.trim(); - if !snippet.is_empty() { - result.push(if original_starts_with_newline { - '\n' - } else { - ' ' - }); - result.push_str(snippet); - if original_ends_with_newline { - force_new_line_for_brace = true; - } - } - } } let pos_before_where = match fd.output { @@ -2585,27 +2558,44 @@ fn rewrite_fn_base( pos_before_where, option, )?; - // If there are neither where-clause nor return type, we may be missing comments between - // params and `{`. - if where_clause_str.is_empty() { - if let ast::FnRetTy::Default(ret_span) = fd.output { - match recover_missing_comment_in_span( - mk_sp(params_span.hi(), ret_span.hi()), - shape, - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - force_new_line_for_brace = true; - } - _ => {} + + result.push_str(&where_clause_str); + if where_clause.predicates.is_empty() { + // Comment between return type and the end of the decl. + // Even if there are no predicates in the where clause, the "where" kw may be present, + // so start the snippet after it. + let snippet_lo = where_clause.span.hi(); + let snippet_hi = span.hi(); + let comment_indent = match where_clause.has_where_token { + true => shape.indent.add(context.config.tab_spaces()), + false => shape.indent, + }; + let mut comment_shape = shape; + comment_shape.indent = comment_indent; + let missing_comment = recover_missing_comment_in_span( + mk_sp(snippet_lo, snippet_hi), + comment_shape, + context, + comment_indent.width(), + ) + .unwrap_or(String::new()); + if !missing_comment.is_empty() { + // If the comment is more than one line, start it at the line after where + if where_clause.has_where_token { + result.push_str(&*format!( + "\n{}where\n{}", + (shape.indent).to_string(context.config), + missing_comment.trim_start_matches('\n'), + )); + } else { + result.push_str(&*missing_comment); } + force_new_line_for_brace = context + .snippet(mk_sp(snippet_lo, snippet_hi)) + .trim_end_matches(' ') + .ends_with('\n'); } } - - result.push_str(&where_clause_str); - let ends_with_comment = last_line_contains_single_line_comment(&result); force_new_line_for_brace |= ends_with_comment; force_new_line_for_brace |= diff --git a/tests/source/issue-4649.rs b/tests/source/issue-4649.rs new file mode 100644 index 00000000000..bc2951c152e --- /dev/null +++ b/tests/source/issue-4649.rs @@ -0,0 +1,9 @@ +trait Bar { + fn bar(&self, a: T) + where + // Self: Bar + // Some comment + ; + + fn bar2(&self, a: T) where /* Self: Bar */ ; +} diff --git a/tests/source/where-clause.rs b/tests/source/where-clause.rs index 6f0df143634..9ff8620bc41 100644 --- a/tests/source/where-clause.rs +++ b/tests/source/where-clause.rs @@ -65,3 +65,13 @@ pub trait AsUnindented { fn f = U>, U>() where U: AsUnindented< Output<'static> = i32> {} + +fn foo2() + where T: FnOnce() +// Comments +{} + +fn foo3() + where T: FnOnce(), // Comments + U: FnOnce() +{} diff --git a/tests/target/issue-1113.rs b/tests/target/issue-1113.rs index 1245bcd057c..d8b69200e72 100644 --- a/tests/target/issue-1113.rs +++ b/tests/target/issue-1113.rs @@ -25,9 +25,9 @@ pub fn foo() -> fmt::Result } pub fn foo() -> fmt::Result /* - * - * - */ + * + * + */ { panic!() } diff --git a/tests/target/issue-4001.rs b/tests/target/issue-4001.rs index 6c1f204eecf..42772611455 100644 --- a/tests/target/issue-4001.rs +++ b/tests/target/issue-4001.rs @@ -1,3 +1,5 @@ -fn unit() -> () /* comment */ { +fn unit() -> () +where + /* comment */ { () } diff --git a/tests/target/issue-4649.rs b/tests/target/issue-4649.rs new file mode 100644 index 00000000000..4980653e771 --- /dev/null +++ b/tests/target/issue-4649.rs @@ -0,0 +1,11 @@ +trait Bar { + fn bar(&self, a: T) + where + // Self: Bar + // Some comment + ; + + fn bar2(&self, a: T) + where + /* Self: Bar */; +} diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs index 86624c33182..025d9abb983 100644 --- a/tests/target/where-clause.rs +++ b/tests/target/where-clause.rs @@ -115,3 +115,14 @@ fn f = U>, U>() where U: AsUnindented = i32> { } + +fn foo2() + where T: FnOnce() // Comments +{ +} + +fn foo3() + where T: FnOnce(), // Comments + U: FnOnce() +{ +}