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


Ignore:
Timestamp:
Jul 1, 2009 12:16:18 PM (5 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.