Add support for overloaded string literals.
[ghc-hetmet.git] / compiler / typecheck / TcPat.lhs
index 933adb8..4fe704a 100644 (file)
@@ -132,7 +132,7 @@ tcCheckExistentialPat pats [] pat_tys body_ty
   = return ()  -- Short cut for case when there are no existentials
 
 tcCheckExistentialPat pats ex_tvs pat_tys body_ty
-  = addErrCtxtM (sigPatCtxt (collectPatsBinders pats) ex_tvs pat_tys body_ty)  $
+  = addErrCtxtM (sigPatCtxt pats ex_tvs pat_tys body_ty)       $
     checkSigTyVarsWrt (tcTyVarsOfTypes (body_ty:pat_tys)) ex_tvs
 
 data PatState = PS {
@@ -332,11 +332,26 @@ tc_pat pstate (BangPat pat) pat_ty thing_inside
 --
 -- Nor should a lazy pattern bind any existential type variables
 -- because they won't be in scope when we do the desugaring
+--
+-- Note [Hopping the LIE in lazy patterns]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- In a lazy pattern, we must *not* discharge constraints from the RHS
+-- from dictionaries bound in the pattern.  E.g.
+--     f ~(C x) = 3
+-- We can't discharge the Num constraint from dictionaries bound by
+-- the pattern C!  
+--
+-- So we have to make the constraints from thing_inside "hop around" 
+-- the pattern.  Hence the getLLE and extendLIEs later.
+
 tc_pat pstate lpat@(LazyPat pat) pat_ty thing_inside
-  = do { (pat', pat_tvs, res) <- tc_lpat pat pat_ty pstate $ \ _ ->
-                                 thing_inside pstate
-                                       -- Ignore refined pstate',
-                                       -- revert to pstate
+  = do { (pat', pat_tvs, (res,lie)) 
+               <- tc_lpat pat pat_ty pstate $ \ _ ->
+                  getLIE (thing_inside pstate)
+               -- Ignore refined pstate', revert to pstate
+       ; extendLIEs lie
+       -- getLIE/extendLIEs: see Note [Hopping the LIE in lazy patterns]
+
        -- Check no existentials
        ; if (null pat_tvs) then return ()
          else lazyPatErr lpat pat_tvs
@@ -540,7 +555,7 @@ tcConPat pstate con_span data_con tycon pat_ty arg_pats thing_inside
        ; ex_tvs' <- tcInstSkolTyVars skol_info ex_tvs  -- Get location from monad,
                                                        -- not from ex_tvs
        ; let tenv     = zipTopTvSubst (univ_tvs ++ ex_tvs)
-                                     (ctxt_res_tys ++ mkTyVarTys ex_tvs')
+                                      (ctxt_res_tys ++ mkTyVarTys ex_tvs')
              eq_spec' = substEqSpec tenv eq_spec
              theta'   = substTheta  tenv theta
              arg_tys' = substTys    tenv arg_tys
@@ -798,6 +813,19 @@ tcOverloadedLit orig lit@(HsFractional r fr) res_ty
   = do         { expr <- newLitInst orig lit res_ty
        ; return (HsFractional r expr) }
 
+tcOverloadedLit orig lit@(HsIsString s fr) res_ty
+  | not (fr `isHsVar` fromStringName)  -- c.f. HsIntegral case
+  = do { str_ty <- tcMetaTy stringTyConName
+       ; fr' <- tcSyntaxOp orig fr (mkFunTy str_ty res_ty)
+       ; return (HsIsString s (HsApp (noLoc fr') (nlHsLit (HsString s)))) }
+
+  | Just expr <- shortCutStringLit s res_ty 
+  = return (HsIsString s expr)
+
+  | otherwise
+  = do         { expr <- newLitInst orig lit res_ty
+       ; return (HsIsString s expr) }
+
 newLitInst :: InstOrigin -> HsOverLit Name -> BoxyRhoType -> TcM (HsExpr TcId)
 newLitInst orig lit res_ty     -- Make a LitInst
   = do         { loc <- getInstLoc orig
@@ -894,7 +922,7 @@ existentialExplode pat
                text "In the binding group for"])
        4 (ppr pat)
 
-sigPatCtxt bound_ids bound_tvs pat_tys body_ty tidy_env 
+sigPatCtxt pats bound_tvs pat_tys body_ty tidy_env 
   = do { pat_tys' <- mapM zonkTcType pat_tys
        ; body_ty' <- zonkTcType body_ty
        ; let (env1,  tidy_tys)    = tidyOpenTypes tidy_env (map idType show_ids)
@@ -907,8 +935,9 @@ sigPatCtxt bound_ids bound_tvs pat_tys body_ty tidy_env
                      ptext SLIT("The body has type:") <+> ppr tidy_body_ty
                ]) }
   where
+    bound_ids = collectPatsBinders pats
     show_ids = filter is_interesting bound_ids
-    is_interesting id = any (`elemVarSet` idFreeTyVars id) bound_tvs
+    is_interesting id = any (`elemVarSet` varTypeTyVars id) bound_tvs
 
     ppr_id id ty = ppr id <+> dcolon <+> ppr ty
        -- Don't zonk the types so we get the separate, un-unified versions