Repository: rust-lang/rustfmt (rust)

Issue:
macro fails to be wrapped if it is exactly one character beyond max_width
```
macro_rules! test {
    ($asdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{
        return;
    }};
}
```
Using rustfmt 1.4.8 nightly with a `.rustfmt.toml` with the following:
```
unstable_features = true
error_on_line_overflow = true
error_on_unformatted = true
#format_macro_matchers = true
```
If this is manually formatted, overflow will not happen. However, if the `format_macro_matchers = true` line is uncommented, the line will always be reformatted to overflow until another character is added.

Pull request:
Fix for #3805 - wrap macro that starts with nested body blocks
Fixes #3805

For wrapping macros with body block that starts with more than one `{`, i.e. starts with "nested blocks". The issue cause was that the nested block(s) `{` were not considered for calculating the remaining line width.

Patch:
diff --git a/src/macros.rs b/src/macros.rs
index ce7d2ce4..6e114c76 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -25,6 +25,7 @@ use crate::comment::{
     contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
 };
 use crate::config::lists::*;
+use crate::config::Version;
 use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
 use crate::lists::{itemize_list, write_list, ListFormatting};
 use crate::overflow;
@@ -1245,8 +1246,16 @@ impl MacroBranch {
             return None;
         }
 
-        // 5 = " => {"
-        let mut result = format_macro_args(context, self.args.clone(), shape.sub_width(5)?)?;
+        let old_body = context.snippet(self.body).trim();
+        let has_block_body = old_body.starts_with('{');
+        let mut prefix_width = 5; // 5 = " => {"
+        if context.config.version() == Version::Two {
+            if has_block_body {
+                prefix_width = 6; // 6 = " => {{"
+            }
+        }
+        let mut result =
+            format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?;
 
         if multi_branch_style {
             result += " =>";
@@ -1264,9 +1273,7 @@ impl MacroBranch {
         // `$$`). We'll try and format like an AST node, but we'll substitute
         // variables for new names with the same length first.
 
-        let old_body = context.snippet(self.body).trim();
         let (body_str, substs) = replace_names(old_body)?;
-        let has_block_body = old_body.starts_with('{');
 
         let mut config = context.config.clone();
         config.set().show_parse_errors(false);


Test patch:
diff --git a/tests/source/issue-3805.rs b/tests/source/issue-3805.rs
new file mode 100644
index 00000000..a0289b57
--- /dev/null
+++ b/tests/source/issue-3805.rs
@@ -0,0 +1,65 @@
+// rustfmt-version: Two
+// rustfmt-format_macro_matchers: true
+
+// From original issue example - Line length 101
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{
+return;
+}};
+}
+
+// Spaces between the `{` and `}`
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {     {
+return;
+}      };
+}
+
+// Multi  `{}`
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{{{
+return;
+}}}};
+}
+
+// Multi  `{}` with spaces
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {    {    {    {
+return;
+}     }     }    };
+}
+    
+// Line length 102
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{
+return;
+}};
+}
+
+// Line length 103
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{
+return;
+}};
+}
+
+// With extended macro body - Line length 101
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{
+let VAR = "VALUE"; return VAR;
+}};
+}
+
+// With extended macro body - Line length 102
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr) => {{
+let VAR = "VALUE"; return VAR;
+}};
+}
+
+// With extended macro body - Line length 103
+macro_rules! test {
+($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr) => {{
+let VAR = "VALUE"; return VAR;
+}};
+}
diff --git a/tests/target/issue-3805.rs b/tests/target/issue-3805.rs
new file mode 100644
index 00000000..a247a43f
--- /dev/null
+++ b/tests/target/issue-3805.rs
@@ -0,0 +1,94 @@
+// rustfmt-version: Two
+// rustfmt-format_macro_matchers: true
+
+// From original issue example - Line length 101
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
+    ) => {{
+        return;
+    }};
+}
+
+// Spaces between the `{` and `}`
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
+    ) => {{
+        return;
+    }};
+}
+
+// Multi  `{}`
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
+    ) => {{
+        {
+            {
+                return;
+            }
+        }
+    }};
+}
+
+// Multi  `{}` with spaces
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
+    ) => {{
+        {
+            {
+                return;
+            }
+        }
+    }};
+}
+
+// Line length 102
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr
+    ) => {{
+        return;
+    }};
+}
+
+// Line length 103
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr
+    ) => {{
+        return;
+    }};
+}
+
+// With extended macro body - Line length 101
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
+    ) => {{
+        let VAR = "VALUE";
+        return VAR;
+    }};
+}
+
+// With extended macro body - Line length 102
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeiou:expr, $add:expr
+    ) => {{
+        let VAR = "VALUE";
+        return VAR;
+    }};
+}
+
+// With extended macro body - Line length 103
+macro_rules! test {
+    (
+        $aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeioua:expr, $add:expr
+    ) => {{
+        let VAR = "VALUE";
+        return VAR;
+    }};
+}