[commit: ghc] wip/hasfield: Solve HasField constraints involving data families (d3809a5)
git at git.haskell.org
git at git.haskell.org
Mon May 16 08:07:36 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/hasfield
Link : http://ghc.haskell.org/trac/ghc/changeset/d3809a56bc66111fad0ae16a7d078aeffa7df145/ghc
>---------------------------------------------------------------
commit d3809a56bc66111fad0ae16a7d078aeffa7df145
Author: Adam Gundry <adam at well-typed.com>
Date: Wed Dec 23 12:20:14 2015 +0000
Solve HasField constraints involving data families
>---------------------------------------------------------------
d3809a56bc66111fad0ae16a7d078aeffa7df145
compiler/typecheck/TcInteract.hs | 23 ++++++++++++++++------
.../overloadedrecflds/should_run/hasfieldrun01.hs | 6 ++++++
.../should_run/hasfieldrun01.stdout | 1 +
3 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/compiler/typecheck/TcInteract.hs b/compiler/typecheck/TcInteract.hs
index ffcb27c..1657549 100644
--- a/compiler/typecheck/TcInteract.hs
+++ b/compiler/typecheck/TcInteract.hs
@@ -2179,8 +2179,19 @@ 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
- = do { env <- getGlobalRdrEnvTcS
+ = do { fam_inst_envs <- getFamInstEnvs
+ -- Look up the representation tycon if this is a data family,
+ -- because that's where the datacons and fields live
+ ; let (rep_tycon, rep_tc_args, _) = tcLookupDataFamInst fam_inst_envs
+ tycon r_args
+
+ -- Check that the field belongs to the tycon, and get its
+ -- selector name from the FieldLabel
+ ; case lookupFsEnv (tyConFieldLabelEnv rep_tycon) x of
+ Nothing -> matchInstEnv dflags clas tys loc
+ Just fl -> do {
+
+ ; env <- getGlobalRdrEnvTcS
-- Check that the field selector is in scope
; case lookupGRE_Field_Name env (flSelector fl) (flLabel fl) of
[] -> matchInstEnv dflags clas tys loc
@@ -2191,7 +2202,7 @@ matchHasField dflags clas tys@[x_ty, r_ty, a_ty] loc
-- there must be at least one data con with the field: find
-- it and hence the field's type.
; let data_cons_with_field = [ (dc, ty)
- | dc <- tyConDataCons tycon
+ | dc <- tyConDataCons rep_tycon
, Just ty <- [dataConFieldType_maybe dc x]
]
(data_con, field_ty) = ASSERT( not (null data_cons_with_field) )
@@ -2200,7 +2211,7 @@ matchHasField dflags clas tys@[x_ty, r_ty, a_ty] loc
-- Calculate the new wanted constraint by equating the actual
-- type of the field (instantiated appropriately) with the
-- type in the third parameter of the HasField constraint.
- tenv = mkTopTCvSubst (dataConUnivTyVars data_con `zip` r_args)
+ tenv = mkTopTCvSubst (dataConUnivTyVars data_con `zip` rep_tc_args)
inst_field_ty = substTy tenv field_ty
theta = mkTyConApp eqPrimTyCon [liftedTypeKind, liftedTypeKind
, inst_field_ty, a_ty ]
@@ -2221,7 +2232,7 @@ matchHasField dflags clas tys@[x_ty, r_ty, a_ty] loc
proxy_ty = mkProxyPrimTy typeSymbolKind x_ty
co = mkTcFunCo Nominal (mkTcReflCo Nominal r_ty)
(evTermCoercion ev)
- body = mkHsWrap (mkWpCastN co <.> mkWpTyApps r_args)
+ body = mkHsWrap (mkWpCastN co <.> mkWpTyApps rep_tc_args)
(HsVar (noLoc sel_id))
ax = case tcInstNewTyCon_maybe (classTyCon clas) tys of
Just x -> snd x
@@ -2232,7 +2243,7 @@ matchHasField dflags clas tys@[x_ty, r_ty, a_ty] loc
, lir_mk_ev = mk_ev
, lir_safe_over = True
})
- } } }
+ } } } }
matchHasField dflags clas tys loc = matchInstEnv dflags clas tys loc
-- | Make a constant lambda-expression
diff --git a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
index eeda42e..7d1cb7f 100644
--- a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
+++ b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.hs
@@ -10,11 +10,16 @@ data T = MkT { foo :: Int, bar :: B }
data U a b = MkU { baf :: a }
+data family V a b c d
+data instance V x Int y [z] = MkVInt { baz :: (x, y, z, Bool) }
+
t = MkT 42 True
u :: U Char Char
u = MkU 'x'
+v = MkVInt (42, 'x', True, False)
+
-- A virtual foo field for U
instance HasField "foo" (U a b) [Char] where
getField _ _ = "virtual"
@@ -23,3 +28,4 @@ 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)
+ print (getField (proxy# :: Proxy# "baz") v)
diff --git a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
index 4c188ae..2b1e91e 100644
--- a/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
+++ b/testsuite/tests/overloadedrecflds/should_run/hasfieldrun01.stdout
@@ -2,3 +2,4 @@
True
'x'
"virtual"
+(42,'x',True,False)
More information about the ghc-commits
mailing list