Merge remote branch 'origin/master' into ghc-generics
authorSimon Peyton Jones <simonpj@microsoft.com>
Wed, 20 Apr 2011 11:55:29 +0000 (12:55 +0100)
committerSimon Peyton Jones <simonpj@microsoft.com>
Wed, 20 Apr 2011 11:55:29 +0000 (12:55 +0100)
1  2 
compiler/hsSyn/HsBinds.lhs
compiler/rename/RnBinds.lhs
compiler/typecheck/TcDeriv.lhs
compiler/typecheck/TcGenDeriv.lhs

@@@ -597,10 -597,6 +597,10 @@@ data Sig name    -- Signatures and pragma
        -- f :: Num a => a -> a
      TypeSig (Located name) (LHsType name)
  
 +        -- A type signature for a generic function inside a class
 +        -- generic eq :: (Representable0 a, GEq (Rep0 a)) => a -> a -> Bool
 +  | GenericSig (Located name) (LHsType name)
 +
        -- A type signature in generated code, notably the code
        -- generated for record selectors.  We simply record
        -- the desired Id itself, replete with its name, type
@@@ -670,31 -666,25 +670,27 @@@ okBindSig :: Sig a -> Boo
  okBindSig _ = True
  
  okHsBootSig :: Sig a -> Bool
 -okHsBootSig (TypeSig  _ _) = True
 -okHsBootSig (FixSig _)           = True
 -okHsBootSig _              = False
 +okHsBootSig (TypeSig  _ _)    = True
 +okHsBootSig (GenericSig  _ _) = True -- JPM: Is this true?
 +okHsBootSig (FixSig _)              = True
 +okHsBootSig _                 = False
  
  okClsDclSig :: Sig a -> Bool
  okClsDclSig (SpecInstSig _) = False
  okClsDclSig _               = True        -- All others OK
  
  okInstDclSig :: Sig a -> Bool
 -okInstDclSig (TypeSig _ _)   = False
 -okInstDclSig (FixSig _)      = False
 -okInstDclSig _                     = True
 +okInstDclSig (TypeSig _ _)    = False
 +okInstDclSig (GenericSig _ _) = False
 +okInstDclSig (FixSig _)       = False
 +okInstDclSig _                      = True
  
- sigForThisGroup :: NameSet -> LSig Name -> Bool
- sigForThisGroup ns sig
-   = case sigName sig of
-       Nothing -> False
-       Just n  -> n `elemNameSet` ns
  sigName :: LSig name -> Maybe name
+ -- Used only in Haddock
  sigName (L _ sig) = sigNameNoLoc sig
  
  sigNameNoLoc :: Sig name -> Maybe name    
+ -- Used only in Haddock
  sigNameNoLoc (TypeSig   n _)          = Just (unLoc n)
  sigNameNoLoc (SpecSig   n _ _)        = Just (unLoc n)
  sigNameNoLoc (InlineSig n _)          = Just (unLoc n)
@@@ -712,10 -702,9 +708,10 @@@ isVanillaLSig (L _(TypeSig {})) = Tru
  isVanillaLSig _                 = False
  
  isTypeLSig :: LSig name -> Bool        -- Type signatures
 -isTypeLSig (L _(TypeSig {})) = True
 -isTypeLSig (L _(IdSig {}))   = True
 -isTypeLSig _                 = False
 +isTypeLSig (L _(TypeSig {}))    = True
 +isTypeLSig (L _(GenericSig {})) = True
 +isTypeLSig (L _(IdSig {}))      = True
 +isTypeLSig _                    = False
  
  isSpecLSig :: LSig name -> Bool
  isSpecLSig (L _(SpecSig {})) = True
@@@ -738,7 -727,6 +734,7 @@@ isInlineLSig _                    = Fal
  
  hsSigDoc :: Sig name -> SDoc
  hsSigDoc (TypeSig {})                 = ptext (sLit "type signature")
 +hsSigDoc (GenericSig {})      = ptext (sLit "generic default type signature")
  hsSigDoc (IdSig {})           = ptext (sLit "id signature")
  hsSigDoc (SpecSig {})         = ptext (sLit "SPECIALISE pragma")
  hsSigDoc (InlineSig {})         = ptext (sLit "INLINE pragma")
@@@ -753,7 -741,6 +749,7 @@@ eqHsSig :: Eq a => LSig a -> LSig a -> 
  eqHsSig (L _ (FixSig (FixitySig n1 _))) (L _ (FixSig (FixitySig n2 _))) = unLoc n1 == unLoc n2
  eqHsSig (L _ (IdSig n1))              (L _ (IdSig n2))                = n1 == n2
  eqHsSig (L _ (TypeSig n1 _))          (L _ (TypeSig n2 _))            = unLoc n1 == unLoc n2
 +eqHsSig (L _ (GenericSig n1 _))               (L _ (GenericSig n2 _))         = unLoc n1 == unLoc n2
  eqHsSig (L _ (InlineSig n1 _))          (L _ (InlineSig n2 _))          = unLoc n1 == unLoc n2
        -- For specialisations, we don't have equality over
        -- HsType, so it's not convenient to spot duplicate 
@@@ -767,7 -754,6 +763,7 @@@ instance (OutputableBndr name) => Outpu
  
  ppr_sig :: OutputableBndr name => Sig name -> SDoc
  ppr_sig (TypeSig var ty)        = pprVarSig (unLoc var) (ppr ty)
 +ppr_sig (GenericSig var ty)     = ptext (sLit "generic") <+> pprVarSig (unLoc var) (ppr ty)
  ppr_sig (IdSig id)              = pprVarSig id (ppr (varType id))
  ppr_sig (FixSig fix_sig)        = ppr fix_sig
  ppr_sig (SpecSig var ty inl)    = pragBrackets (pprSpec var (ppr ty) inl)
@@@ -588,20 -588,8 +588,20 @@@ rnMethodBinds :: Name                    -- Class nam
              -> RnM (LHsBinds Name, FreeVars)
  
  rnMethodBinds cls sig_fn gen_tyvars binds
 -  = foldlM do_one (emptyBag,emptyFVs) (bagToList binds)
 +  = do { checkDupRdrNames meth_names
 +           -- Check that the same method is not given twice in the
 +           -- same instance decl      instance C T where
 +           --                       f x = ...
 +           --                       g y = ...
 +           --                       f x = ...
 +           -- We must use checkDupRdrNames because the Name of the
 +           -- method is the Name of the class selector, whose SrcSpan
 +           -- points to the class declaration; and we use rnMethodBinds
 +           -- for instance decls too
 +
 +       ; foldlM do_one (emptyBag, emptyFVs) (bagToList binds) }
    where 
 +    meth_names  = collectMethodBinders binds
      do_one (binds,fvs) bind 
         = do { (bind', fvs_bind) <- rnMethodBind cls sig_fn gen_tyvars bind
            ; return (binds `unionBags` bind', fvs_bind `plusFV` fvs) }
@@@ -677,12 -665,7 +677,12 @@@ renameSigs mb_names ok_sig sig
                -- Check for duplicates on RdrName version, 
                -- because renamed version has unboundName for
                -- not-in-scope binders, which gives bogus dup-sig errors
 -
 +              -- NB: in a class decl, a 'generic' sig is not considered 
 +              --     equal to an ordinary sig, so we allow, say
 +              --           class C a where
 +              --             op :: a -> a
 +              --             generic op :: Eq a => a -> a
 +              
        ; sigs' <- mapM (wrapLocM (renameSig mb_names)) sigs
  
        ; let (good_sigs, bad_sigs) = partition (ok_sig . unLoc) sigs'
@@@ -709,11 -692,6 +709,11 @@@ renameSig mb_names sig@(TypeSig v ty
        ; new_ty <- rnHsSigType (quotes (ppr v)) ty
        ; return (TypeSig new_v new_ty) }
  
 +renameSig mb_names sig@(GenericSig v ty)
 +  = do        { new_v <- lookupSigOccRn mb_names sig v
 +      ; new_ty <- rnHsSigType (quotes (ppr v)) ty
 +      ; return (GenericSig new_v new_ty) } -- JPM: ?
 +
  renameSig _ (SpecInstSig ty)
    = do        { new_ty <- rnLHsType (text "A SPECIALISE instance pragma") ty
        ; return (SpecInstSig new_ty) }
  -- {-# SPECIALISE #-} pragmas can refer to imported Ids
  -- so, in the top-level case (when mb_names is Nothing)
  -- we use lookupOccRn.  If there's both an imported and a local 'f'
- -- then the SPECIALISE pragma is ambiguous, unlike alll other signatures
+ -- then the SPECIALISE pragma is ambiguous, unlike all other signatures
  renameSig mb_names sig@(SpecSig v ty inl)
    = do        { new_v <- case mb_names of
                       Just {} -> lookupSigOccRn mb_names sig v
@@@ -40,13 -40,10 +40,13 @@@ import Nam
  import NameSet
  import TyCon
  import TcType
 +import BuildTyCl
 +import BasicTypes
  import Var
  import VarSet
  import PrelNames
  import SrcLoc
 +import UniqSupply
  import Util
  import ListSetOps
  import Outputable
@@@ -295,14 -292,12 +295,14 @@@ both of them.  So we gather defs/uses f
  tcDeriving  :: [LTyClDecl Name]  -- All type constructors
              -> [LInstDecl Name]  -- All instance declarations
              -> [LDerivDecl Name] -- All stand-alone deriving declarations
 -          -> TcM ([InstInfo Name],    -- The generated "instance decls"
 -                  HsValBinds Name,    -- Extra generated top-level bindings
 -                    DefUses)
 +            -> TcM ([InstInfo Name] -- The generated "instance decls"
 +                   ,HsValBinds Name -- Extra generated top-level bindings
 +                   ,DefUses
 +                   ,[TyCon]         -- Extra generated top-level types
 +                   ,[TyCon])        -- Extra generated type family instances
  
  tcDeriving tycl_decls inst_decls deriv_decls
 -  = recoverM (return ([], emptyValBindsOut, emptyDUs)) $
 +  = recoverM (return ([], emptyValBindsOut, emptyDUs, [], [])) $
      do        {       -- Fish the "deriving"-related information out of the TcEnv
                -- And make the necessary "equations".
          is_boot <- tcIsHsBoot
  
        ; insts2 <- mapM (genInst False overlap_flag) final_specs
  
 -               -- Generate the generic to/from functions from each type declaration
 -      ; gen_binds <- mkGenericBinds is_boot tycl_decls
 -      ; (inst_info, rn_binds, rn_dus) <- renameDeriv is_boot gen_binds (insts1 ++ insts2)
 +               -- Generate the (old) generic to/from functions from each type declaration
 +      ; gen_binds <- return emptyBag -- mkGenericBinds is_boot tycl_decls
 +      
 +       -- Generate the generic Representable0/1 instances from each type declaration
 +  ; repInstsMeta <- genGenericRepBinds is_boot tycl_decls
 +      
 +      ; let repInsts   = concat (map (\(a,_,_) -> a) repInstsMeta)
 +            repMetaTys = map (\(_,b,_) -> b) repInstsMeta
 +            repTyCons  = map (\(_,_,c) -> c) repInstsMeta
 +      -- Should we extendLocalInstEnv with repInsts?
 +
 +      ; (inst_info, rn_binds, rn_dus) <- renameDeriv is_boot gen_binds (insts1 ++ insts2 ++ repInsts)
 +
 +      ; dflags <- getDOpts
 +      ; liftIO (dumpIfSet_dyn dflags Opt_D_dump_deriv "Derived instances"
 +               (ddump_deriving inst_info rn_binds))
  
          ; when (not (null inst_info)) $
            dumpDerivingInfo (ddump_deriving inst_info rn_binds)
 -
 -      ; return (inst_info, rn_binds, rn_dus) }
 +      ; return ( inst_info, rn_binds, rn_dus
 +                 , concat (map metaTyCons2TyCons repMetaTys), repTyCons) }
    where
      ddump_deriving :: [InstInfo Name] -> HsValBinds Name -> SDoc
      ddump_deriving inst_infos extra_binds
@@@ -405,7 -387,6 +405,7 @@@ renameDeriv is_boot gen_binds inst
          clas_nm            = className clas
  
  -----------------------------------------
 +{- Now unused 
  mkGenericBinds :: Bool -> [LTyClDecl Name] -> TcM (LHsBinds RdrName)
  mkGenericBinds is_boot tycl_decls
    | is_boot 
                -- We are only interested in the data type declarations,
                -- and then only in the ones whose 'has-generics' flag is on
                -- The predicate tyConHasGenerics finds both of these
 +-}
  \end{code}
  
  Note [Newtype deriving and unused constructors]
@@@ -1302,7 -1282,7 +1302,7 @@@ inferInstanceContexts oflag infer_spec
      gen_soln (DS { ds_loc = loc, ds_orig = orig, ds_tvs = tyvars 
                 , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs })
        = setSrcSpan loc        $
-       addErrCtxt (derivInstCtxt clas inst_tys) $ 
+       addErrCtxt (derivInstCtxt the_pred) $ 
        do {      -- Check for a bizarre corner case, when the derived instance decl should
                  -- have form  instance C a b => D (T a) where ...
                  -- Note that 'b' isn't a parameter of T.  This gives rise to all sorts
                                       , not (tyVarsOfPred pred `subVarSet` tv_set)]  
           ; mapM_ (addErrTc . badDerivedPred) weird_preds      
  
-            ; theta <- simplifyDeriv orig tyvars deriv_rhs
+            ; theta <- simplifyDeriv orig the_pred tyvars deriv_rhs
                -- checkValidInstance tyvars theta clas inst_tys
                -- Not necessary; see Note [Exotic derived instance contexts]
                --                in TcSimplify
                -- Hence no need to call:
                --   checkValidInstance tyvars theta clas inst_tys
           ; return (sortLe (<=) theta) }       -- Canonicalise before returning the solution
+       where
+         the_pred = mkClassPred clas inst_tys
  
  ------------------------------------------------------------------
  mkInstance :: OverlapFlag -> ThetaType -> DerivSpec -> Instance
@@@ -1483,133 -1465,6 +1485,133 @@@ genDerivBinds loc fix_env clas tyco
               ,(foldableClassKey, gen_Foldable_binds)
               ,(traversableClassKey, gen_Traversable_binds)
               ]
 +
 +-- Generate the binds for the generic representation
 +genGenericRepBinds :: Bool -> [LTyClDecl Name] 
 +                   -> TcM [([(InstInfo RdrName, DerivAuxBinds)]
 +                           , MetaTyCons, TyCon)]
 +genGenericRepBinds isBoot tyclDecls
 +  | isBoot    = return []
 +  | otherwise = do
 +      allTyDecls <- mapM tcLookupTyCon [ tcdName d | L _ d <- tyclDecls
 +                                       , isDataDecl d ]
 +      let tyDecls = filter tyConHasGenerics allTyDecls
 +      inst1 <- mapM genGenericRepBind tyDecls
 +      let (_repInsts, metaTyCons, _repTys) = unzip3 inst1
 +      metaInsts <- ASSERT (length tyDecls == length metaTyCons)
 +                     mapM genDtMeta (zip tyDecls metaTyCons)
 +      return (ASSERT (length inst1 == length metaInsts)
 +                [ (ri : mi, ms, rt) 
 +                | ((ri, ms, rt), mi) <- zip inst1 metaInsts ])
 +
 +genGenericRepBind :: TyCon -> TcM ((InstInfo RdrName, DerivAuxBinds)
 +                                  , MetaTyCons, TyCon)
 +genGenericRepBind tc =
 +  do  clas <- tcLookupClass rep0ClassName
 +      uniqS <- newUniqueSupply
 +      dfun_name <- new_dfun_name clas tc
 +      let
 +        -- Uniques for everyone
 +        (uniqD:uniqs) = uniqsFromSupply uniqS
 +        (uniqsC,us) = splitAt (length tc_cons) uniqs
 +        uniqsS :: [[Unique]] -- Unique supply for the S datatypes
 +        uniqsS = mkUniqsS tc_arits us
 +        mkUniqsS []    _  = []
 +        mkUniqsS (n:t) us = case splitAt n us of
 +                              (us1,us2) -> us1 : mkUniqsS t us2
 +
 +        tc_name   = tyConName tc
 +        tc_cons   = tyConDataCons tc
 +        tc_arits  = map dataConSourceArity tc_cons
 +        
 +        tc_occ    = nameOccName tc_name
 +        d_occ     = mkGenD tc_occ
 +        c_occ m   = mkGenC tc_occ m
 +        s_occ m n = mkGenS tc_occ m n
 +        mod_name  = nameModule (tyConName tc)
 +        d_name    = mkExternalName uniqD mod_name d_occ wiredInSrcSpan
 +        c_names   = [ mkExternalName u mod_name (c_occ m) wiredInSrcSpan
 +                      | (u,m) <- zip uniqsC [0..] ]
 +        s_names   = [ [ mkExternalName u mod_name (s_occ m n) wiredInSrcSpan 
 +                        | (u,n) <- zip us [0..] ] | (us,m) <- zip uniqsS [0..] ]
 +        tvs       = tyConTyVars tc
 +        tc_ty     = mkTyConApp tc (mkTyVarTys tvs)
 +        
 +        mkTyCon name = ASSERT( isExternalName name )
 +                         buildAlgTyCon name [] [] mkAbstractTyConRhs
 +                           NonRecursive False False NoParentTyCon Nothing
 +
 +      metaDTyCon  <- mkTyCon d_name
 +      metaCTyCons <- sequence [ mkTyCon c_name | c_name <- c_names ]
 +      metaSTyCons <- mapM sequence 
 +                       [ [ mkTyCon s_name 
 +                         | s_name <- s_namesC ] | s_namesC <- s_names ]
 +
 +      let metaDts = MetaTyCons metaDTyCon metaCTyCons metaSTyCons
 +  
 +      rep0_tycon <- tc_mkRep0TyCon tc metaDts
 +
 +      let
 +        mkInstRep0 = (InstInfo { iSpec = inst, iBinds = binds }
 +                               , [ {- No DerivAuxBinds -} ])
 +        inst  = mkLocalInstance dfun NoOverlap
 +        binds = VanillaInst (mkBindsRep0 tc) [] False
 +        
 +        dfun  = mkDictFunId dfun_name (tyConTyVars tc) [] clas [tc_ty]
 +      return (mkInstRep0, metaDts, rep0_tycon)
 +      
 +genDtMeta :: (TyCon, MetaTyCons) -> TcM [(InstInfo RdrName, DerivAuxBinds)]
 +genDtMeta (tc,metaDts) =
 +  do  dClas <- tcLookupClass datatypeClassName
 +      d_dfun_name <- new_dfun_name dClas tc
 +      cClas <- tcLookupClass constructorClassName
 +      c_dfun_names <- sequence [ new_dfun_name cClas tc | _ <- metaC metaDts ]
 +      sClas <- tcLookupClass selectorClassName
 +      s_dfun_names <- sequence (map sequence [ [ new_dfun_name sClas tc 
 +                                               | _ <- x ] 
 +                                             | x <- metaS metaDts ])
 +      fix_env <- getFixityEnv
 +
 +      let
 +        (dBinds,cBinds,sBinds) = mkBindsMetaD fix_env tc
 +        
 +        -- Datatype
 +        d_metaTycon = metaD metaDts
 +        d_inst = mkLocalInstance d_dfun NoOverlap
 +        d_binds = VanillaInst dBinds [] False
 +        d_dfun  = mkDictFunId d_dfun_name (tyConTyVars tc) [] dClas 
 +                    [ mkTyConTy d_metaTycon ]
 +        d_mkInst = (InstInfo { iSpec = d_inst, iBinds = d_binds }, [])
 +        
 +        -- Constructor
 +        c_metaTycons = metaC metaDts
 +        c_insts = [ mkLocalInstance (c_dfun c ds) NoOverlap 
 +                  | (c, ds) <- myZip1 c_metaTycons c_dfun_names ]
 +        c_binds = [ VanillaInst c [] False | c <- cBinds ]
 +        c_dfun c dfun_name = mkDictFunId dfun_name (tyConTyVars tc) [] cClas 
 +                               [ mkTyConTy c ]
 +        c_mkInst = [ (InstInfo { iSpec = is, iBinds = bs }, []) 
 +                   | (is,bs) <- myZip1 c_insts c_binds ]
 +        
 +        -- Selector
 +        s_metaTycons = metaS metaDts
 +        s_insts = map (map (\(s,ds) -> mkLocalInstance (s_dfun s ds) NoOverlap))
 +                    (myZip2 s_metaTycons s_dfun_names)
 +        s_binds = [ [ VanillaInst s [] False | s <- ss ] | ss <- sBinds ]
 +        s_dfun s dfun_name = mkDictFunId dfun_name (tyConTyVars tc) [] sClas
 +                               [ mkTyConTy s ]
 +        s_mkInst = map (map (\(is,bs) -> (InstInfo {iSpec=is, iBinds=bs}, [])))
 +                     (myZip2 s_insts s_binds)
 +       
 +        myZip1 :: [a] -> [b] -> [(a,b)]
 +        myZip1 l1 l2 = ASSERT (length l1 == length l2) zip l1 l2
 +        
 +        myZip2 :: [[a]] -> [[b]] -> [[(a,b)]]
 +        myZip2 l1 l2 =
 +          ASSERT (and (zipWith (>=) (map length l1) (map length l2)))
 +            [ zip x1 x2 | (x1,x2) <- zip l1 l2 ]
 +        
 +      return (d_mkInst : c_mkInst ++ concat s_mkInst)
  \end{code}
  
  
@@@ -1658,9 -1513,9 +1660,9 @@@ standaloneCtxt :: LHsType Name -> SDo
  standaloneCtxt ty = hang (ptext (sLit "In the stand-alone deriving instance for")) 
                       2 (quotes (ppr ty))
  
- derivInstCtxt :: Class -> [Type] -> Message
- derivInstCtxt clas inst_tys
-   = ptext (sLit "When deriving the instance for") <+> parens (pprClassPred clas inst_tys)
+ derivInstCtxt :: PredType -> Message
+ derivInstCtxt pred
+   = ptext (sLit "When deriving the instance for") <+> parens (ppr pred)
  
  badDerivedPred :: PredType -> Message
  badDerivedPred pred
@@@ -42,7 -42,7 +42,7 @@@ import Nam
  import HscTypes
  import PrelInfo
  import MkCore ( eRROR_ID )
 -import PrelNames
 +import PrelNames hiding (error_RDR)
  import PrimOp
  import SrcLoc
  import TyCon
@@@ -893,15 -893,15 +893,15 @@@ gen_Read_binds get_fixity loc tyco
      read_nullary_cons 
        = case nullary_cons of
            []    -> []
-           [con] -> [nlHsDo DoExpr [bindLex (match_con con)] (result_expr con [])]
+           [con] -> [nlHsDo DoExpr (match_con con) (result_expr con [])]
              _     -> [nlHsApp (nlHsVar choose_RDR) 
                              (nlList (map mk_pair nullary_cons))]
          -- NB For operators the parens around (:=:) are matched by the
        -- enclosing "parens" call, so here we must match the naked
        -- data_con_str con
  
-     match_con con | isSym con_str = symbol_pat con_str
-                   | otherwise     = ident_pat  con_str
+     match_con con | isSym con_str = [symbol_pat con_str]
+                   | otherwise     = ident_h_pat  con_str
                    where
                      con_str = data_con_str con
        -- For nullary constructors we must match Ident s for normal constrs
        prefix_parser = mk_parser prefix_prec prefix_stmts body
  
        read_prefix_con
-           | isSym con_str = [read_punc "(", bindLex (symbol_pat con_str), read_punc ")"]
-           | otherwise     = [bindLex (ident_pat con_str)]
+           | isSym con_str = [read_punc "(", symbol_pat con_str, read_punc ")"]
+           | otherwise     = ident_h_pat con_str
         
        read_infix_con
-           | isSym con_str = [bindLex (symbol_pat con_str)]
-           | otherwise     = [read_punc "`", bindLex (ident_pat con_str), read_punc "`"]
+           | isSym con_str = [symbol_pat con_str]
+           | otherwise     = [read_punc "`"] ++ ident_h_pat con_str ++ [read_punc "`"]
  
                prefix_stmts            -- T a b c
                  = read_prefix_con ++ read_args
      result_expr con as = nlHsApp (nlHsVar returnM_RDR) (con_app con as)               -- return (con as)
      
      punc_pat s   = nlConPat punc_RDR   [nlLitPat (mkHsString s)]  -- Punc 'c'
-     ident_pat s  = nlConPat ident_RDR  [nlLitPat (mkHsString s)]  -- Ident "foo"
-     symbol_pat s = nlConPat symbol_RDR [nlLitPat (mkHsString s)]  -- Symbol ">>"
+     -- For constructors and field labels ending in '#', we hackily
+     -- let the lexer generate two tokens, and look for both in sequence
+     -- Thus [Ident "I"; Symbol "#"].  See Trac #5041
+     ident_h_pat s | Just (ss, '#') <- snocView s = [ ident_pat ss, symbol_pat "#" ]
+                   | otherwise                    = [ ident_pat s ]
+                                          
+     ident_pat  s = bindLex $ nlConPat ident_RDR  [nlLitPat (mkHsString s)]  -- Ident "foo" <- lexP
+     symbol_pat s = bindLex $ nlConPat symbol_RDR [nlLitPat (mkHsString s)]  -- Symbol ">>" <- lexP
      
      data_con_str con = occNameString (getOccName con)
      
        -- or   (#) = 4
        -- Note the parens!
      read_lbl lbl | isSym lbl_str 
-                = [read_punc "(", 
-                   bindLex (symbol_pat lbl_str),
-                   read_punc ")"]
+                = [read_punc "(", symbol_pat lbl_str, read_punc ")"]
                 | otherwise
-                = [bindLex (ident_pat lbl_str)]
+                = ident_h_pat lbl_str
                 where  
                   lbl_str = occNameString (getOccName lbl) 
  \end{code}