Changes between Version 2 and Version 3 of Commentary/Compiler/UnusedImports


Ignore:
Timestamp:
Jul 1, 2009 12:16:18 PM (6 years ago)
Author:
igloo
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Commentary/Compiler/UnusedImports

    v2 v3  
    113113seeing the RdrNames, not by knowing that the name 'x' is used.
    114114
    115 I think that all lookups go through a single function,
    116    `RnEnv.lookupGreRn_maybe`
    117 So in `RnEnv.lookupGreRn_maybe`, if `(gre_prov gre)` is `(Imported _)`
    118 hen put `rdr_name` in a new
    119 {{{
    120 tcg_used_imports :: TcRef (Set RdrName)
    121 }}}
    122 in `TcGblEnv`.  All the `tcg_used_imports` are in scope; if not,
    123 we report an error and do not add it to `tct_used_imports`.
     115I think that all lookups go through either, `RnEnv.lookupGreRn_maybe` or `RnEnv.lookup_sub_bndr`.
     116So in `RnEnv.lookupGreRn_maybe`, if `(gre_prov gre)` is `(Imported _)`,
     117and in `RnEnv.lookup_sub_bndr`,
     118put `rdr_name` in a new
     119{{{
     120tcg_used_rdrnames :: TcRef (Set RdrName)
     121}}}
     122in `TcGblEnv`.  All the `tcg_used_rdrnames` are in scope; if not,
     123we report an error and do not add it to `tcg_used_rdrnames`.
    124124
    125125Other notes
     
    137137  * We can compare `ImportSpecs` for equality by their `SrcSpans`
    138138
    139 
    140 Also perhpas:
    141 
    142139  * In `TcRnDriver.tcRnImports`, save import_decls in a new
    143140  `tcg_rn_rdr_imports :: Maybe [LImportDecl RdrName]`
    144141  in `TcGblEnv`
    145142
    146   * In `RnNames.reportUnusedNames`, call a function that actually does the
    147   hard work. The ugly part is when we have an import of Foo(..). Then we
    148   need to dig through the environments, similar to what
    149   `RnNames.exports_from_avail` does, so that we can expand the (..).
    150 
    151 
     143----
     144
     145The algorithm for deciding which imports have been used is based around this datatype:
     146{{{
     147data ImportInfo = ImportInfo SrcSpan
     148                             SDoc
     149                             [RdrName] -- The names the import provides
     150                             Bool -- Has it been used yet?
     151                             [ImportInfo] -- Child import infos
     152}}}
     153Here are how some example imports map to trees of `ImportInfo`, assuming `Foo` exports `a`, `b`, `D(c1, c2)`:
     154{{{
     155import Foo
     156->
     157ImportInfo "Foo" ["a", "b", "D", "c1", "c2", "Foo.a", "Foo.b", "Foo.D", "Foo.c1", "Foo.c2"]
     158
     159import qualified Foo as Bar
     160->
     161ImportInfo "Foo" ["Bar.a", "Bar.b", "Bar.D", "Bar.c1", "Bar.c2"]
     162
     163import qualified Foo (a, D)
     164->
     165ImportInfo "Foo" []
     166    ImportInfo "Foo" ["Foo.a"]
     167    ImportInfo "Foo" ["Foo.D"]
     168
     169import qualified Foo hiding (a, D(..))
     170->
     171ImportInfo "Foo" ["Foo.b"]
     172
     173import Foo (D(c1, c2))
     174->
     175ImportInfo "Foo" []
     176    ImportInfo "Foo" ["D", "Foo.D"]
     177        ImportInfo "Foo" ["c1", "Foo.c1"]
     178        ImportInfo "Foo" ["c2", "Foo.c2"]
     179
     180import qualified Foo (D(..))
     181->
     182ImportInfo "Foo" []
     183    ImportInfo "Foo" ["Foo.D", "Foo.c1", "Foo.c2"]
     184}}}
     185
     186If a node in the tree is marked as used, then so are all nodes above it. For example, given the tree
     187{{{
     188ImportInfo "Foo" []
     189    ImportInfo "Foo" ["D", "Foo.D"]
     190        ImportInfo "Foo" ["c1", "Foo.c1"]
     191        ImportInfo "Foo" ["c2", "Foo.c2"]
     192}}}
     193a use of `"D"` marks both the first and second lines as used.
     194
     195When we come to giving warnings, if a node is unused then we warn about it, and do not descend into the rest of that subtree, as the node we warn about subsumes its children. If the node is marked as used then we descend, looking to see if any of its children are unused.
     196
     197These trees are built by `RnNames.mkImportInfo`. In `RnNames.warnUnusedImportDecls` we make two lists of `ImportInfo`s; one list contains all the explicit imports, e.g.
     198{{{
     199import Foo (a, b)
     200}}}
     201and the other contains the implicit imports, e.g.
     202{{{
     203import Foo
     204import Foo hiding (a, b)
     205}}}
     206
     207Then `RnNames.markUsages` is called for each `RdrName` that was used in the program. The current implementation marks all explicit import as used unless there are no such imports, in which case it marks all implicit imports as used. A small tweak to `markUsages` would allow it to mark only the first import it finds as used.
     208
     209As well as the `RdrName`s used in the source, we also need to mark as used the names that are exported. We first call `RnNames.expandExports` to expand `D(..)` into `D(c1, c2)`, and then call `RnNames.markExportUsages`. Normally this just marks the `RdrName`s as used in the same way that uses in the module body are handled, but it is also possible for an entire module to be "used", if `module Foo` is in the export list. In this case `RnNames.markModuleUsed` does the hard work, marking every module imported with that name as used.