[commit: ghc] wip/lazy-instance-matching: InstEnv: Ensure that instance visibility check is lazy (3c2ce1d)
git at git.haskell.org
git at git.haskell.org
Tue Jul 19 05:53:21 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/lazy-instance-matching
Link : http://ghc.haskell.org/trac/ghc/changeset/3c2ce1d19bc79d05049f220d191676699b3d02f5/ghc
>---------------------------------------------------------------
commit 3c2ce1d19bc79d05049f220d191676699b3d02f5
Author: Ben Gamari <ben at smart-cactus.org>
Date: Tue Jul 19 07:39:56 2016 +0200
InstEnv: Ensure that instance visibility check is lazy
Previously instIsVisible had completely broken the laziness of
lookupInstEnv' since it would examine is_dfun_name to check the name of
the defining module (to know whether it is an interactive module). This
resulted in the visibility check drawing in an interface file
unnecessarily.
>---------------------------------------------------------------
3c2ce1d19bc79d05049f220d191676699b3d02f5
compiler/iface/TcIface.hs | 2 +-
compiler/types/InstEnv.hs | 27 ++++++++++++++++++---------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
index f366c51..a551c96 100644
--- a/compiler/iface/TcIface.hs
+++ b/compiler/iface/TcIface.hs
@@ -657,7 +657,7 @@ tcIfaceInst (IfaceClsInst { ifDFun = dfun_occ, ifOFlag = oflag
= do { dfun <- forkM (text "Dict fun" <+> ppr dfun_occ) $
tcIfaceExtId dfun_occ
; let mb_tcs' = map (fmap ifaceTyConName) mb_tcs
- ; return (mkImportedInstance cls mb_tcs' dfun oflag orph) }
+ ; return (mkImportedInstance cls mb_tcs' dfun_occ dfun oflag orph) }
tcIfaceFamInst :: IfaceFamInst -> IfL FamInst
tcIfaceFamInst (IfaceFamInst { ifFamInstFam = fam, ifFamInstTys = mb_tcs
diff --git a/compiler/types/InstEnv.hs b/compiler/types/InstEnv.hs
index a8b5f0f..e87d732 100644
--- a/compiler/types/InstEnv.hs
+++ b/compiler/types/InstEnv.hs
@@ -61,6 +61,12 @@ data ClsInst
is_cls_nm :: Name -- Class name
, is_tcs :: [Maybe Name] -- Top of type args
+ -- We use this for the visibility check, instIsVisible. Note how
+ -- we cannot use the Module attached to is_dfun, since doing so
+ -- would mean we would potentially pull in an entire interface
+ -- file unnecessarily. This was the cause of #12367.
+ , is_dfun_name :: Name -- Defining module
+
-- Used for "proper matching"; see Note [Proper-match fields]
, is_tvs :: [TyVar] -- Fresh template tyvars for full match
-- See Note [Template tyvars are fresh]
@@ -226,9 +232,10 @@ mkLocalInstance :: DFunId -> OverlapFlag
mkLocalInstance dfun oflag tvs cls tys
= ClsInst { is_flag = oflag, is_dfun = dfun
, is_tvs = tvs
+ , is_dfun_name = dfun_name
, is_cls = cls, is_cls_nm = cls_name
, is_tys = tys, is_tcs = roughMatchTcs tys
- , is_orphan = orph
+ , is_orphan = pprTrace "mkLocalInstance" empty orph
}
where
cls_name = className cls
@@ -257,21 +264,23 @@ mkLocalInstance dfun oflag tvs cls tys
choose_one nss = chooseOrphanAnchor (unionNameSets nss)
-mkImportedInstance :: Name
- -> [Maybe Name]
- -> DFunId
- -> OverlapFlag
- -> IsOrphan
+mkImportedInstance :: Name -- ^ the name of the class
+ -> [Maybe Name] -- ^ the types which the class was applied to
+ -> Name -- ^ the 'Name' of the dictionary binding
+ -> DFunId -- ^ the 'Id' of the dictionary.
+ -> OverlapFlag -- ^ may this instance overlap?
+ -> IsOrphan -- ^ is this instance an orphan?
-> ClsInst
-- Used for imported instances, where we get the rough-match stuff
-- from the interface file
-- The bound tyvars of the dfun are guaranteed fresh, because
-- the dfun has been typechecked out of the same interface file
-mkImportedInstance cls_nm mb_tcs dfun oflag orphan
+mkImportedInstance cls_nm mb_tcs dfun_name dfun oflag orphan
= ClsInst { is_flag = oflag, is_dfun = dfun
, is_tvs = tvs, is_tys = tys
+ , is_dfun_name = dfun_name
, is_cls_nm = cls_nm, is_cls = cls, is_tcs = mb_tcs
- , is_orphan = orphan }
+ , is_orphan = pprTrace "mkImportedInstance" empty orphan }
where
(tvs, _, cls, tys) = tcSplitDFunTy (idType dfun)
@@ -397,7 +406,7 @@ instIsVisible vis_mods ispec
| IsOrphan <- is_orphan ispec = mod `elemModuleSet` vis_mods
| otherwise = True
where
- mod = nameModule (idName (is_dfun ispec))
+ mod = nameModule $ is_dfun_name ispec
classInstances :: InstEnvs -> Class -> [ClsInst]
classInstances (InstEnvs { ie_global = pkg_ie, ie_local = home_ie, ie_visible = vis_mods }) cls
More information about the ghc-commits
mailing list