[commit: ghc] wip/hasfield: Initial work on magic solving of HasField constraints (8966ab3)

git at git.haskell.org git at git.haskell.org
Mon May 16 08:07:13 UTC 2016


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/hasfield
Link       : http://ghc.haskell.org/trac/ghc/changeset/8966ab38686b8d7d000d4caeaafafd0fa503d050/ghc

>---------------------------------------------------------------

commit 8966ab38686b8d7d000d4caeaafafd0fa503d050
Author: Adam Gundry <adam at well-typed.com>
Date:   Tue Dec 22 16:12:40 2015 +0000

    Initial work on magic solving of HasField constraints


>---------------------------------------------------------------

8966ab38686b8d7d000d4caeaafafd0fa503d050
 compiler/typecheck/TcInteract.hs | 76 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 4 deletions(-)

diff --git a/compiler/typecheck/TcInteract.hs b/compiler/typecheck/TcInteract.hs
index 78bf845..c0e37b0 100644
--- a/compiler/typecheck/TcInteract.hs
+++ b/compiler/typecheck/TcInteract.hs
@@ -9,7 +9,7 @@ module TcInteract (
 
 #include "HsVersions.h"
 
-import BasicTypes ( infinity, IntWithInf, intGtLimit )
+import BasicTypes ( infinity, IntWithInf, intGtLimit, Origin(Generated) )
 import HsTypes ( HsIPName(..) )
 import FastString
 import TcCanonical
@@ -22,22 +22,29 @@ import CoAxiom( sfInteractTop, sfInteractInert )
 import Var
 import TcType
 import Name
+import RdrName ( lookupGRE_Field_Name )
 import PrelNames ( knownNatClassName, knownSymbolClassName,
                    typeableClassName, coercibleTyConKey,
-                   heqTyConKey )
+                   heqTyConKey, hasFieldClassName )
 import TysWiredIn ( ipClass, typeNatKind, typeSymbolKind, heqDataCon,
                     coercibleDataCon )
-import TysPrim    ( eqPrimTyCon, eqReprPrimTyCon )
+import TysPrim    ( eqPrimTyCon, eqReprPrimTyCon, mkProxyPrimTy )
 import Id( idType )
 import CoAxiom ( Eqn, CoAxiom(..), CoAxBranch(..), fromBranches )
 import Class
 import TyCon
-import DataCon( dataConWrapId )
+import DataCon( dataConWrapId, dataConFieldType_maybe, dataConUnivTyVars )
+import FieldLabel
 import FunDeps
 import FamInst
 import FamInstEnv
 import Unify ( tcUnifyTyWithTFs )
 
+import HsBinds ( emptyLocalBinds )
+import HsExpr
+import HsPat ( Pat(WildPat) )
+import HsUtils ( mkHsWrap )
+
 import TcEvidence
 import Outputable
 
@@ -1794,6 +1801,7 @@ match_class_inst dflags clas tys loc
   | cls_name == typeableClassName     = matchTypeable        clas tys
   | clas `hasKey` heqTyConKey         = matchLiftedEquality       tys
   | clas `hasKey` coercibleTyConKey   = matchLiftedCoercible      tys
+  | cls_name == hasFieldClassName     = matchHasField        clas tys
   | otherwise                         = matchInstEnv dflags clas tys loc
   where
     cls_name = className clas
@@ -2115,3 +2123,63 @@ matchLiftedCoercible args@[k, t1, t2]
   where
     args' = [k, k, t1, t2]
 matchLiftedCoercible args = pprPanic "matchLiftedCoercible" (ppr args)
+
+
+{- ********************************************************************
+*                                                                     *
+              Class lookup for overloaded record fields
+*                                                                     *
+***********************************************************************-}
+
+matchHasField :: Class -> [Type] -> TcS LookupInstResult
+matchHasField clas tys@[x_ty, r_ty, a_ty]
+  | Just x <- isStrLitTy x_ty
+  , Just (tycon, r_args) <- tcSplitTyConApp_maybe r_ty
+  , Just fl <- lookupFsEnv (tyConFieldLabelEnv tycon) x
+  , Just (_, ax) <- tcInstNewTyCon_maybe (classTyCon clas) tys
+  = do { env <- getGlobalRdrEnvTcS
+       ; let gres = lookupGRE_Field_Name env (flSelector fl) (flLabel fl)
+       ; case gres of
+           []      -> return NoInstance
+           (gre:_) -> do {
+       ; addUsedGRE True gre
+       ; sel_id <- tcLookupId (flSelector fl)
+
+       ; let data_cons_with_field = [ (dc, ty)
+                                    | dc <- tyConDataCons tycon
+                                    , Just ty <- [dataConFieldType_maybe dc x]
+                                    ]
+             (data_con, field_ty) = ASSERT( not (null data_cons_with_field) ) head data_cons_with_field
+             tenv = mkTopTCvSubst (dataConUnivTyVars data_con `zip` r_args)
+             inst_field_ty = substTy tenv field_ty
+             theta = mkTyConApp eqPrimTyCon [liftedTypeKind, liftedTypeKind, inst_field_ty, a_ty ]
+
+       ; let mk_ev [ev] = EvCast (EvExpr (mkHsLamConst proxy_ty (mkFunTy r_ty a_ty) body)) (mkTcSymCo ax)
+               where
+                proxy_ty = mkProxyPrimTy typeSymbolKind x_ty
+                co = mkTcFunCo Nominal (mkTcReflCo Nominal r_ty) (evTermCoercion ev)
+                body = mkHsWrap (mkWpCastN co <.> mkWpTyApps r_args) (HsVar (noLoc sel_id))
+
+             mk_ev _ = panic "matchHasField.mk_ev"
+
+       ; return (GenInst { lir_new_theta = [ theta ]
+                         , lir_mk_ev     = mk_ev
+                         , lir_safe_over = True
+                         })
+       } }
+matchHasField _ _ = return NoInstance
+
+mkHsLamConst :: Type -> Type -> HsExpr Id -> HsExpr Id
+mkHsLamConst arg_ty res_ty body = HsLam mg
+  where
+    m  = Match { m_fixity = NonFunBindMatch
+               , m_pats   = [noLoc (WildPat arg_ty)]
+               , m_type   = Nothing
+               , m_grhss  = GRHSs { grhssGRHSs = [noLoc (GRHS [] (noLoc body))]
+                                  , grhssLocalBinds = noLoc emptyLocalBinds }
+               }
+    mg = MG { mg_alts = noLoc [noLoc m]
+            , mg_arg_tys = [arg_ty]
+            , mg_res_ty  = res_ty
+            , mg_origin  = Generated
+            }



More information about the ghc-commits mailing list