Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* Reference assembly MVIDs are now deterministic across compiler invocations. Previously, `--refout` / `<ProduceReferenceAssembly>true</ProduceReferenceAssembly>` produced a different MVID every build because the implied signature hash used .NET's randomized `String.GetHashCode()`. ([Issue #19751](https://github.com/dotnet/fsharp/issues/19751), [PR #19801](https://github.com/dotnet/fsharp/pull/19801))
* Parser: recover on unfinished if and binary expressions
([PR #19724](https://github.com/dotnet/fsharp/pull/19724))
* Fix `SynExpr.shouldBeParenthesizedInContext` to report parentheses as required around `SynExpr.Sequential` expressions used as record or anonymous-record field values, so the IDE "remove unnecessary parentheses" analyzer no longer breaks code like `{| A = ((); B = 3) |}`. ([Issue #17826](https://github.com/dotnet/fsharp/issues/17826))

### Added

Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/Service/SynExpr.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,11 @@ module SynExpr =
| SynInterpolatedStringPart.FillExpr(qualifiers = Some _) -> true
| _ -> false)

// {| A = (1; 2) |}
// { A = (1; 2) }
// Removing the parens would let the semicolon be parsed as a field separator.
| (SynExpr.Record _ | SynExpr.AnonRecd _), SynExpr.Sequential _ -> true

// { (!x) with … }
| SynExpr.Record(copyInfo = Some(SynExpr.Paren(expr = Is inner), _)),
SynExpr.App(isInfix = false; funcExpr = FuncExpr.SymbolicOperator(StartsWith('!' | '~')))
Expand Down
11 changes: 11 additions & 0 deletions tests/FSharp.Compiler.Service.Tests/SynExprTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ let exprs: obj array list =
}
"
|]
// https://github.com/dotnet/fsharp/issues/17826
// Sequential expressions used as record / anonymous record field values
// require their enclosing parentheses - otherwise the semicolon is parsed
// as a field separator.
[|[Needed]; "{| A = (1; 2) |}"|]
[|[Needed]; "{ A = (1; 2) }"|]
[|[Needed]; "{| A = ((); B = 3) |}"|]
[|[Needed]; "{| A = (printfn \"hi\"; 3) |}"|]
[|[Needed]; "{ existing with A = (1; 2) }"|]
[|[Needed; Needed]; "{| A = (1; 2); B = (3; 4) |}"|]
[|[Needed; Unneeded]; "{ Outer = ({ Inner = (1; 2) }) }"|]
]

#if !NET6_0_OR_GREATER
Expand Down
Loading