diff --git a/compiler/fmt/src/expr.rs b/compiler/fmt/src/expr.rs index f3ff643633..1881787a8c 100644 --- a/compiler/fmt/src/expr.rs +++ b/compiler/fmt/src/expr.rs @@ -861,6 +861,14 @@ fn fmt_backpassing<'a>( indent }; + let pattern_needs_parens = loc_patterns + .iter() + .any(|p| pattern_needs_parens_when_backpassing(&p.value)); + + if pattern_needs_parens { + buf.push('('); + } + let mut it = loc_patterns.iter().peekable(); while let Some(loc_pattern) = it.next() { @@ -876,6 +884,10 @@ fn fmt_backpassing<'a>( } } + if pattern_needs_parens { + buf.push(')'); + } + if arguments_are_multiline { newline(buf, indent); } else { @@ -896,7 +908,7 @@ fn fmt_backpassing<'a>( // the body of the Backpass can be on the same line, or // on a new line. If it's on the same line, insert a space. - match &loc_ret.value { + match &loc_body.value { SpaceBefore(_, _) => { // the body starts with (first comment and then) a newline // do nothing @@ -911,6 +923,16 @@ fn fmt_backpassing<'a>( loc_ret.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent); } +fn pattern_needs_parens_when_backpassing(pat: &Pattern) -> bool { + match pat { + Pattern::Apply(_, _) => true, + Pattern::SpaceBefore(a, _) | Pattern::SpaceAfter(a, _) => { + pattern_needs_parens_when_backpassing(a) + } + _ => false, + } +} + fn fmt_record<'a>( buf: &mut String<'a>, update: Option<&'a Located>>, diff --git a/compiler/fmt/tests/test_fmt.rs b/compiler/fmt/tests/test_fmt.rs index 24a239fe11..057e7e0a52 100644 --- a/compiler/fmt/tests/test_fmt.rs +++ b/compiler/fmt/tests/test_fmt.rs @@ -2714,6 +2714,46 @@ mod test_fmt { )); } + #[test] + fn backpassing_simple() { + expr_formats_same(indoc!( + r#" + getChar = \ctx -> + x <- Task.await (getCharScope scope) + 42 + + 42 + "# + )); + } + + #[test] + fn backpassing_apply_tag() { + expr_formats_same(indoc!( + r#" + getChar = \ctx -> + (T val newScope) <- Task.await (getCharScope scope) + 42 + + 42 + "# + )); + } + + #[test] + fn backpassing_body_on_newline() { + expr_formats_same(indoc!( + r#" + getChar = \ctx -> + x <- + Task.await (getCharScope scope) + 42 + + 42 + "# + )); + } + // this is a parse error atm // #[test] // fn multiline_apply() {