Opened 2 years ago

Closed 2 years ago

#9915 closed bug (fixed)

GHCi has trouble with 'foreign' when it is not a keyword

Reported by: cactus Owned by: cactus
Priority: normal Milestone: 7.10.1
Component: Compiler (Parser) Version: 7.8.3
Keywords: GHCi Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: ghci/should_compile/T9915
Blocked By: Blocking: #9900
Related Tickets: Differential Rev(s):
Wiki Page:


In Haskell 98 mode, foreign is not a keyword at all. The following is an example of a valid Haskell 98 program:

{-# LANGUAGE Haskell98 #-}
module F where

foreign :: Int
foreign = 42

However, it seems noone told GHCi about this:

12:42:38 [cactus@galaxy hs]$ ghci -XHaskell98
GHCi, version 7.8.3:  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
λ» x = 42 -- Expected to fail

<interactive>:2:3: parse error on input ‘=’
λ» x -- Expected to fail

<interactive>:3:1: Not in scope: ‘x’
λ» -- So this should fail as well, right?
λ» foreign = 42
λ» -- Nope
λ» foreign
λ» -- But wait, there's more!
λ» foreign -- boo!

    Parse error: naked expression at top level
    Perhaps you intended to use TemplateHaskell

Change History (6)

comment:1 Changed 2 years ago by cactus

Of course, this is because InteractiveUI.runStmt decides to evaluate lines as declarations instead of statements based on a check vs. some hardcoded prefixes:

-- | Entry point to execute some haskell code from user
runStmt :: String -> SingleStep -> GHCi Bool
runStmt stmt step
 -- empty
 | null (filter (not.isSpace) stmt)
 = return False

 -- import
 | "import " `isPrefixOf` stmt
 = do addImportToContext stmt; return False

 -- data, class, newtype...
 | any (flip isPrefixOf stmt) declPrefixes
 = ... -- parse and run as Decl

 | otherwise
 = ... -- parse and run as Stmt

-- | If we one of these strings prefixes a command, then we treat it as a decl
-- rather than a stmt.
declPrefixes :: [String]
declPrefixes = ["class ","data ","newtype ","type ","instance ", "deriving ",
                "foreign ", "default ", "default("]

This gives a wrong result when foreign is not a keyword (and thus, a prefix of foreign doesn't signify a declaration, like in the foreign -- boo! line in my original ticket).

comment:2 Changed 2 years ago by cactus

Owner: set to cactus

comment:3 Changed 2 years ago by Dr. ERDI Gergo <gergo@…>

In 3b497ddb231981bc6aeb5533426bf632ba126e39/ghc:

Check dflags for language extensions when deciding if "foreign " and "deriving "
look like prefixes of valid declarations (fixes #9915)

comment:4 Changed 2 years ago by cactus

Milestone: 7.8.4
Status: newmerge
Test Case: ghci/should_compile/T9915

comment:5 Changed 2 years ago by cactus

Blocking: 9900 added

comment:6 Changed 2 years ago by thoughtpolice

Resolution: fixed
Status: mergeclosed

7.8.4 is already done; closing.

Note: See TracTickets for help on using tickets.