```
todo += [m for m in depinfo.modules if m not in mods and m in nametofile]
```
`mods` only accumulates modules from previous iterations of the outer while
loop. Within a single iteration, modules in the current batch are added to
mods one at a time as `moddep.items()` is iterated. This means two distinct
failure modes:
1. Cross-dependency within a batch: if modules A and B are both in the current
todo and both depend on X, X passes the m not in mods check when processing
A's deps and again when processing B's (since X hasn't been added to mods
yet). X ends up in todo twice.
2. Intra-batch back-edge: if A depends on B and both are already in the current
todo/moddep, B still passes m not in mods when processing A's dep list,
queuing B for a redundant second modinfo call in the next iteration.
Both boil down to the same root cause: the check doesn't account for modules
currently being processed.
The fix addresses both issues:
1. `m not in moddep.keys()` prevents modules from the current batch being
re-queued into the next iteration's `todo`.
2. Turning`todo` into a set prevents a module from appearing *multiple times*
in the same next `todo`, when two modules in the current batch share a
dependency
Because these duplicates frequently occur in practice, eliminating them
provides an incremental speedup on top of the original optimization
made in GH4092/GH4017.