ndmitchell / hlint

Haskell source code suggestions
Other
1.45k stars 194 forks source link

QuasiQuotes with # at start of line fail to parse #1564

Open TeofilC opened 5 months ago

TeofilC commented 5 months ago

Take the following module:

{-# LANGUAGE QuasiQuotes #-}

foo = [undefined| foo
#{_hello}|]

This features a quasiqoute that runs over several lines. And one of those lines starts with a #, which makes it look a bit like CPP but it isn't.

HLint gives the following output:

Warning: unknown directive #{_hello}|]
in Test.hs  at line 4 col 1
Test.hs:(3,18)-(5,0): Error: Parse error: Test.hs:3:18: error: [GHC-21231]
    unterminated quasiquotation at end of input
Found:
    {-# LANGUAGE QuasiQuotes #-}

  > foo = [undefined| foo

Yet GHC correctly parses this. (Though the use of undefined then gives us an error later)

shayne-fletcher commented 5 months ago

left to itself, hlint will default enable its own selection of language extensions. apparently one of the extensions it is default enabling causes this problem. we can override this. putting -XHaskell98 overcomes the parse error.

update: i guess it's CPP that is getting default enabled. -XNoCPP also overcomes the parse failure.

TeofilC commented 5 months ago

Excellent yes it does look like CPP is to blame

shayne-fletcher commented 5 months ago

what's happening is that when CPP is enabled, hlint runs a cpp preprocessor. when it does that, after preprocessing the resulting program is

foo = [undefined| foo

which is indeed an unterminated quasiquote. another workaround is to put a leading space before the # e.g.

{-# LANGUAGE QuasiQuotes #-}

foo = [undefined| foo
 #{_hello}|]
TeofilC commented 5 months ago

Thanks! I'm not sure if this ticket should be closed now.

I guess the missing piece is that if another user runs into this, they'd have to search to find these workarounds. I'm not sure if hlint could direct them towards them somehow