haskell / happy

The Happy parser generator for Haskell
Other
276 stars 84 forks source link

HappyWrap newtypes #134

Closed int-index closed 5 years ago

int-index commented 5 years ago

Fix #137

This fix is much better than #133, as it accounts for constraints (as demonstrated by the modified rank2 test case).

In addition to that, it fixes a problem with -c which made all polymorphic definitions unsafe. This grammar used to be accepted:

{
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
module Main where

import System.IO
import Data.Char
}

%name calc
%tokentype { Token }

%token tok { Token }

%monad { IO } { (>>=) } { return }

%%

a :: { Bool }
   : n { $1 }

n :: { a }
  : { (0::Int) }

{
main = calc [] >>= print

data Token = Token

lexer :: String -> [Token]
lexer _ = []

happyError tokens = ioError (userError "parse error")
}

It unsafeCoerce-d 0::Int to Bool and printed False.

With this patch it's rejected:

tests/rank2.hs:33:34: error: Not in scope: type variable ‘a’
   |
33 | newtype HappyWrap5 = HappyWrap5 (a)
   |  

Polymorphism with -c now requires explicit forall. If we add it like so:

n :: { forall a. a }
  : { (0::Int) }

We now get a proper error:

tests/rank2.hs:99:20: error:
    • Couldn't match expected type ‘a’ with actual type ‘Int’
      ‘a’ is a rigid type variable bound by
        a type expected by the context:
          forall a. a
        at tests/rank2.hs:(98,22)-(100,9)
    • In the first argument of ‘happyIn5’, namely ‘((0 :: Int))’
      In the expression: happyIn5 ((0 :: Int))
      In an equation for ‘happyReduction_2’:
          happyReduction_2 = happyIn5 ((0 :: Int))
   |
99 |                  ((0::Int)
   |     
int-index commented 5 years ago

@simonmar, ping? --coerce barely works without this fix.

int-index commented 5 years ago

Thanks!