From 3bf67c175dfa9b1bcb35f001da53b49c21e2179b Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 9 Jul 2020 19:56:46 -0700 Subject: [PATCH] Don't drop blocks on foreign functions A code like ```rust extern "C" { fn f() { fn g() {} } } ``` is incorrect and does not compile. Today rustfmt formats this in a way that is correct: ```rust extern "C" { fn f(); } ``` But this loses information, and doesn't have to be done because we know the content of the block if it is present. During development I don't think rustfmt should drop the block in this context. Closes #4313 --- src/items.rs | 18 +++++++++++++++++- src/visitor.rs | 2 +- tests/target/issue-4313.rs | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-4313.rs diff --git a/src/items.rs b/src/items.rs index 3c30de1a417..039dd1e1ae0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3043,7 +3043,23 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.kind { - ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( + ast::ForeignItemKind::Fn(defaultness, ref fn_sig, ref generics, Some(ref body)) => { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.last_pos = self.span.lo(); + let inner_attrs = inner_attributes(&self.attrs); + let fn_ctxt = visit::FnCtxt::Foreign; + visitor.visit_fn( + visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)), + generics, + &fn_sig.decl, + self.span, + defaultness, + Some(&inner_attrs), + ); + Some(visitor.buffer.to_owned()) + } + ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, None) => rewrite_fn_base( context, shape.indent, self.ident, diff --git a/src/visitor.rs b/src/visitor.rs index ecf72833195..3b9b0a2f967 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -370,7 +370,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. - fn visit_fn( + pub(crate) fn visit_fn( &mut self, fk: visit::FnKind<'_>, generics: &ast::Generics, diff --git a/tests/target/issue-4313.rs b/tests/target/issue-4313.rs new file mode 100644 index 00000000000..c390ee6ba30 --- /dev/null +++ b/tests/target/issue-4313.rs @@ -0,0 +1,5 @@ +extern "C" { + fn f() { + fn g() {} + } +}