https://issues.dlang.org/show_bug.cgi?id=17630
--- Comment #2 from Seb <greensunn...@gmail.com> --- > Can you investigate this a bit more and add that info to the bug report, > including that it's been around for a while? The leaked symbols are [found in the local `symtab` table](https://github.com/dlang/dmd/blob/master/src/ddmd/dsymbol.d#L1306) ``` test17630b.ScopeDsymbol::search(ident='Erase', flags=x0) found in locals = 'test17630b.Erase' test17630b.ScopeDsymbol::search(ident='Erase', flags=x28) found in locals = 'test17630b.Erase' ``` However, the next four lines in the log shouldn't happen: ``` test17630a.ScopeDsymbol::search(ident='Erase', flags=x0) found in locals = 'test17630a.Erase' test17630a.ScopeDsymbol::search(ident='Erase', flags=x28) found in locals = 'test17630a.Erase' __anonymous.ScopeDsymbol::search(ident='Erase', flags=x8) found in locals = '__anonymous.Erase' ``` Now, when I look at the symbol table for test17630b it's built correctly: ``` DsymbolTable::insert(this = 0x7fc6d7dcbbe0, 'object') DsymbolTable::insert(this = 0x7fc6d7dcbbe0, 'Erase') DsymbolTable::insert(this = 0x7fc6d7dcbbe0, 'NoErase') ``` In fact even the members only get added for test17630b: ``` Import.addMember(this=object, sd=test17630b, sc=0x7f11f8e71b00) Dsymbol::addMember('object') Dsymbol::addMember(this = 0x7f11f8e71c20, 'object' scopesym = 'test17630b') Dsymbol::addMember(this = 0x7f11f8e71c20, 'object' sds = 0x7f11fa2c2db0, sds.symtab = 0x7f11f8e71d30) Dsymbol::addMember('Erase') Dsymbol::addMember(this = 0x7f11fa2c3aa0, 'Erase' scopesym = 'test17630b') Dsymbol::addMember(this = 0x7f11fa2c3aa0, 'Erase' sds = 0x7f11fa2c2db0, sds.symtab = 0x7f11f8e71d30) Dsymbol::addMember('NoErase') Dsymbol::addMember(this = 0x7f11fa2c3c60, 'NoErase' scopesym = 'test17630b') Dsymbol::addMember(this = 0x7f11fa2c3c60, 'NoErase' sds = 0x7f11fa2c2db0, sds.symtab = 0x7f11f8e71d30) ``` and in the main test file `Erase` doesn't get inserted into the symbol table: ``` __anonymous.ScopeDsymbol::search(ident='_Dmain', flags=x8) __entrypoint.ScopeDsymbol::search(ident='_Dmain', flags=x28) found in locals = '__entrypoint._Dmain' Import::semantic('imports.test17630a.object') object test17630a.ScopeDsymbol::importScope(object, 2) Import::semantic('imports.test17630a.imports') test17630b test17630a.ScopeDsymbol::importScope(test17630b, 2) Import::semantic('imports.test17630b.object') object test17630b.ScopeDsymbol::importScope(object, 2) DsymbolTable::insert(this = 0x7f975b424780, 'fail17630') DsymbolTable::insert(this = 0x7f975b424850, 'imports') DsymbolTable::insert(this = 0x7f975b424920, 'imports') DsymbolTable::insert(this = 0x7f975b4249f0, 'fail17630') Import::semantic('__anonymous') test17630a Import::load('__anonymous') 0x7f975c8294b0 ``` > This seems like a fairly important import leak remaining, would be good to > explore how large it is. It's _pretty_ large. AFAICT all module-level imports, non-selective imports leak their symbols. However, even selective imports leak their selected symbols: ```d import imports.test17630b; // works __falsely__ as public import import imports.test17630b : Erase; // works __falsely__ as public import ``` Funnily even `private import X;` doesn't fix it. --