A strange parse error

The following program has a parse error: the line _x :: () <- pure () shouldn’t be indented. But the error message is really bad. It’s about the do in the True case branch! Does anyone understand why? (It seems to really subtly depend on some other features of the program too. If they’re changed then the error message improves.)

foo :: IO ()
-- The error changes to something more reasonable
-- if this do is removed.
foo = do
  case True of
    -- There's an error message on this "do"
    --
    -- error: [GHC-06446]
    -- do-notation in pattern
    True -> do
      pure ()

    False -> do
      -- The error changes to something more
      -- reasonable if this let is removed
      let _ = ()

          -- The error changes to something more
          -- reasonable if the type siganture is
          -- removed
          _x :: () <- pure ()

      pure ()
1 Like

This is perhaps a simpler example:

foo = do
  (case x of 
    False -> do bar
    True -> baz) <- qux

It strangely reports the error at the do bar instead of the whole case .... Edit: I’m guessing the case is tentatively allowed because it might occur in a valid view pattern, but do is completely out of the question so it fails there. Edit2: No that can’t be it because do is allowed in view patterns, e.g. do (do fst -> y) <- Just (1, 2); Just y.

If you remove the parentheses then it still gives the same error.

1 Like

I think the reason is simply that this is a valid AST before post-processing.

At the <- Happy reports a parse error to Alex, who recovers by closing the layouts for the let and inner do, at which point the tree for the outer do statement reduces to exp '<-', so the post-processing logic for disambiguating patterns from expressions is run, and “do-notation in pattern” is the first error it encounters.

1 Like

But why doesn’t it report (case ... of ...)-syntax in pattern? That is what you get when you try this example:

foo = do case x of () -> () <- pure ()

I’d assume it’s because of the evaluation order in class DisambECP.

  -- | Disambiguate "case ... of ..."
  mkHsCasePV :: SrcSpan -> LHsExpr GhcPs -> (LocatedL [LMatch GhcPs (LocatedA b)])
             -> EpAnnHsCase -> PV (LocatedA b)

This is called with an un-disambiguated LHsExpr for the scrutinee, but the matches need to be of type b already (which is PatBuilder for patterns), so the do expression in there has probably been processed by mkHsDoPV first, which adds a fatal error that terminates parsing.