Note [Prepare TyClGroup FVs]
The renamer returns, alongside each renamed type/class declaration or instance,
the set of its free variables:
rnTyClDecl :: TyClDecl GhcPs -> RnM (TyClDecl GhcRn, FreeVars)
rnSrcInstDecl :: InstDecl GhcPs -> RnM (InstDecl GhcRn, FreeVars)
For example:
type family F (a :: k) -- FVs: {}
data X = MkX Char (Maybe X) -- FVs: {Char, Maybe, X}
data Y = MkY X (Maybe Y) -- FVs: {Maybe, Y, X}
type instance F MkX = X -- FVs: {F, MkX, X}
type instance F MkY = Int -- FVs: {F, MkY, Int}
This is almost what we need for dependency analysis (i.e. to figure out in which
order to check the declarations), but first we apply a few transformations:
* toParents rdr_env inst_fvs `intersectFVs` tc_names -- in mkInstGroups
* toParents rdr_env node_fvs `intersectFVs` tc_names -- in depAnalTyClDecls
* delFVs node_bndrs (plusFVs nodes_deps) -- in rnTyClGroups
The cited lines of code are somewhat far apart; to see the big picture, refer
to Note [Dependency analysis of type and class decls], and more specifically
steps TCDEP3, TCDEP5, and TCDEP6.
The cumulative effect of these transformations is as follows:
* Data constructor names are replaced by the parent type constructors:
{MkX} ==> {X}
Part of the code:
toParents rdr_env
Reason:
MkX does not get its own node in the dependency graph,
so we cannot make an edge to it in `depAnalTyClDecls`
* Names defined outside the current HsGroup are filtered out:
{Char,Maybe} ==> {}
Part of the code:
`intersectFVs` tc_names
Reason:
makes the NameSet smaller, so there are fewer subsequent lookups
in `graphFromEdgedVertices` (GHC.Data.Graph.Directed)
and in `isReadyTyClGroup` (GHC.Tc.TyCl)
* Self-references are removed:
{A,B,C} ==> {C}, iff in the TyClGroup that defines {A,B}
Part of the code:
delFVs node_bndrs
Reason:
avoids the problem that `isReadyTyClGroup` would otherwise consider
a recursive TyClGroup to be blocked on itself
Note:
needs to happen after the SCC analysis because of
mutually-recursive data types
These "prepared" FVs are the lexical dependencies of a TyClGroup that are stored
in the XCTyClGroup extension field:
type family F (a :: k) -- XCTyClGroup: {}
data X = MkX Char (Maybe X) -- XCTyClGroup: {}
data Y = MkY X (Maybe Y) -- XCTyClGroup: {X}
type instance F MkX = X -- XCTyClGroup: {F, X}
type instance F MkY = Int -- XCTyClGroup: {F, Y}
Before attempting to kind-check a TyClGroup, all of its lexical dependencies
need to be satisfied, i.e. there must be a TyThing in the TypeEnv for each of
these names.
Imported names {Char,Maybe} don't need to be explicitly included in the set of
lexical dependencies because `isReadyTyClGroup` can safely assume those are
definitely already in the env. References 1
- Dependency analysis of type and class decls GHC.Rename.Module
Referenced by 6
- GHC.Rename.Module call site ×3
- Dependency analysis of type and class decls GHC.Rename.Module ×2
- GHC.Hs.Decls call site