[commit: ghc] wip/hasfield: Support virtual fields via manual HasField instances (9a390aa)
git at git.haskell.org
git at git.haskell.org
Mon May 16 08:07:23 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/hasfield
Link : http://ghc.haskell.org/trac/ghc/changeset/9a390aa6277b6c21fe69b662d2dbd398c48523f2/ghc
>---------------------------------------------------------------
commit 9a390aa6277b6c21fe69b662d2dbd398c48523f2
Author: Adam Gundry <adam at well-typed.com>
Date: Tue Dec 22 16:56:04 2015 +0000
Support virtual fields via manual HasField instances
>---------------------------------------------------------------
9a390aa6277b6c21fe69b662d2dbd398c48523f2
compiler/typecheck/TcInteract.hs | 12 ++++++------
.../tests/overloadedrecflds/should_run/hasfieldrun01.hs | 12 ++++++++++--
.../tests/overloadedrecflds/should_run/hasfieldrun01.stdout | 1 +
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/compiler/typecheck/TcInteract.hs b/compiler/typecheck/TcInteract.hs
index d246b15..66cacea 100644
--- a/compiler/typecheck/TcInteract.hs
+++ b/compiler/typecheck/TcInteract.hs
@@ -1801,7 +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
+ | cls_name == hasFieldClassName = matchHasField dflags clas tys loc
| otherwise = matchInstEnv dflags clas tys loc
where
cls_name = className clas
@@ -2131,8 +2131,8 @@ matchLiftedCoercible args = pprPanic "matchLiftedCoercible" (ppr args)
* *
***********************************************************************-}
-matchHasField :: Class -> [Type] -> TcS LookupInstResult
-matchHasField clas tys@[x_ty, r_ty, a_ty]
+matchHasField :: DynFlags -> Class -> [Type] -> CtLoc -> TcS LookupInstResult
+matchHasField dflags clas tys@[x_ty, r_ty, a_ty] loc
| Just x <- isStrLitTy x_ty
, Just (tycon, r_args) <- tcSplitTyConApp_maybe r_ty
, Just fl <- lookupFsEnv (tyConFieldLabelEnv tycon) x
@@ -2140,7 +2140,7 @@ matchHasField clas tys@[x_ty, r_ty, a_ty]
= do { env <- getGlobalRdrEnvTcS
; let gres = lookupGRE_Field_Name env (flSelector fl) (flLabel fl)
; case gres of
- [] -> return NoInstance
+ [] -> matchInstEnv dflags clas tys loc
(gre:_) -> do {
; addUsedGRE True gre
; sel_id <- tcLookupId (flSelector fl)
@@ -2155,7 +2155,7 @@ matchHasField clas tys@[x_ty, r_ty, a_ty]
theta = mkTyConApp eqPrimTyCon [liftedTypeKind, liftedTypeKind, inst_field_ty, a_ty ]
; if isNaughtyRecordSelector sel_id || not (isTauTy inst_field_ty)
- then return NoInstance
+ then matchInstEnv dflags clas tys loc
else do {
; let mk_ev [ev] = EvCast (EvExpr (mkHsLamConst proxy_ty (mkFunTy r_ty a_ty) body)) (mkTcSymCo ax)
@@ -2171,7 +2171,7 @@ matchHasField clas tys@[x_ty, r_ty, a_ty]
, lir_safe_over = True
})
} } }
-matchHasField _ _ = return NoInstance
+matchHasField dflags clas tys loc = matchInstEnv dflags clas tys loc
mkHsLamConst :: Type -> Type -> HsExpr Id -> HsExpr Id
mkHsLamConst arg_ty res_ty body = HsLam mg
diff --git a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
index 0f27c6b..eeda42e 100644
--- a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
+++ b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
@@ -1,7 +1,8 @@
-{-# LANGUAGE DataKinds, MagicHash, TypeFamilies #-}
+{-# LANGUAGE DataKinds, FlexibleInstances, MagicHash,
+ MultiParamTypeClasses, TypeFamilies #-}
import GHC.Prim (Proxy#, proxy#)
-import GHC.Records (getField)
+import GHC.Records (HasField(..))
type family B where B = Bool
@@ -10,8 +11,15 @@ data T = MkT { foo :: Int, bar :: B }
data U a b = MkU { baf :: a }
t = MkT 42 True
+
+u :: U Char Char
u = MkU 'x'
+-- A virtual foo field for U
+instance HasField "foo" (U a b) [Char] where
+ getField _ _ = "virtual"
+
main = do print (getField (proxy# :: Proxy# "foo") t)
print (getField (proxy# :: Proxy# "bar") t)
print (getField (proxy# :: Proxy# "baf") u)
+ print (getField (proxy# :: Proxy# "foo") u)
diff --git a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
index 1bfbe7a..4c188ae 100644
--- a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
+++ b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
@@ -1,3 +1,4 @@
42
True
'x'
+"virtual"
More information about the ghc-commits
mailing list