Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fantomas introduces meaningless match block #1806

Closed
1 of 3 tasks
Smaug123 opened this issue Jul 2, 2021 · 4 comments · Fixed by #1807
Closed
1 of 3 tasks

Fantomas introduces meaningless match block #1806

Smaug123 opened this issue Jul 2, 2021 · 4 comments · Fixed by #1807

Comments

@Smaug123
Copy link
Contributor

Smaug123 commented Jul 2, 2021

Issue created from fantomas-online

Code

module Foo =
    let bar () =
        {
            Foo =
                blah
                |> Struct.map (fun _ (a, _, _) -> filterBackings a)
        }

Result

module Foo =
    let bar () =
        { Foo =
              blah
              |> Struct.map
                  (fun _ (a, _, _) ->
                      match _arg2 with
                      | _ ->
                          match _arg2 with
                          | _ -> filterBackings a) }

Problem description

I honestly have not the faintest idea how this could have happened, but anyway, the additional match block is not meant to be there.

Extra information

  • The formatted result breaks by code.
  • The formatted result gives compiler warnings.
  • I or my company would be willing to help fix this.

Options

Fantomas Master at 07/01/2021 18:56:12 - 3a12872

Default Fantomas configuration

Did you know that you can ignore files when formatting from fantomas-tool or the FAKE targets by using a .fantomasignore file?

@auduchinok
Copy link
Contributor

auduchinok commented Jul 2, 2021

The parser does some desugaring for lambdas, and these nested matches are what the type checker is actually dealing with later.

@nojaf I've added the originally parsed lambdas to the tree in dotnet/fsharp#10166 to workaround this problem in our plugin, you can try using it too.

@nojaf
Copy link
Contributor

nojaf commented Jul 2, 2021

Yep, that is exactly what I'm using and has been really helpful.
The challenge here seems to be finding the correct body expression.

let (|Lambda|_|) =
function
| SynExpr.Lambda (_, _, _, _, Some (pats, body), range) ->
let maxDepth =
match pats with
| [ PatParen (PatTuple ts) ] -> List.length ts
| _ -> List.length pats
// find the body expression from the last lambda
let rec visit (currentDepth: int) (e: SynExpr) : SynExpr =
if currentDepth < maxDepth then
match e with
| SynExpr.Match (matchSeqPoint = NoDebugPointAtInvisibleBinding; clauses = [ Clause (_, expr, _) ])
| SynExpr.Lambda (_, _, _, SynExpr.Match(clauses = [ Clause (_, expr, _) ]), _, _) ->
visit (currentDepth + 1) expr
| _ -> e
else
e
Some(pats, visit 0 body, range)
| _ -> None

@auduchinok
Copy link
Contributor

auduchinok commented Jul 2, 2021

I might've added some incorrect range or expression in the PR, since I've found I had also added a workaround for getting the body, see skipGeneratedMatch here. We should probably fix it in FCS. :)

@nojaf
Copy link
Contributor

nojaf commented Jul 3, 2021

Many thanks for the pointer there. I'll check if I can fix this in FCS sometime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants