pub struct ModuleWalker<'a> { /* private fields */ }Implementations§
Source§impl<'a> ModuleWalker<'a>
impl<'a> ModuleWalker<'a>
Sourcepub fn new(
modules: &'a [Module],
module_files: &HashMap<Name, SourceFileId>,
package: &PackageName,
) -> Result<ModuleWalker<'a>, Error>
pub fn new( modules: &'a [Module], module_files: &HashMap<Name, SourceFileId>, package: &PackageName, ) -> Result<ModuleWalker<'a>, Error>
module_files is how a cycle’s edges learn which file each import was
written in (CycleEdge::file) — this is driver code, the same as
check_in_order below, so it is handed the map compile_package already
built while parsing rather than trying to discover it itself. Every test in
this module passes an empty map: their modules are hand-built, with no file
on disk to name, and CycleEdge::file degrades to None for them exactly
as documented there.
Sourcepub fn new_for_root(
modules: &'a [Module],
module_files: &HashMap<Name, SourceFileId>,
package: &PackageName,
) -> Result<ModuleWalker<'a>, Error>
pub fn new_for_root( modules: &'a [Module], module_files: &HashMap<Name, SourceFileId>, package: &PackageName, ) -> Result<ModuleWalker<'a>, Error>
A walker over the modules of one of a package’s two source roots.
A package has a src/ and a tests/, and each is walked and checked on its own,
but whether package is exempt from the default imports
(PackageName::is_core) does not depend
on which root — or which modules — either one happens to hold, so the two roots
of one package always get the same answer without either walker having to be
told the other’s modules.
The import graph is built from modules alone either way. An import naming a
module of the other root resolves through an
Interface or not at all, the same as an import
naming another package’s module.
Sourcepub fn check_in_order<M: Checked, E>(
&self,
package: &PackageName,
interfaces: &mut HashMap<Name, Interface>,
module_files: &HashMap<Name, SourceFileId>,
check: fn(package: &PackageName, interfaces: &HashMap<Name, Interface>, source: &Module) -> Outcome<M, E>,
) -> Vec<Outcome<M, E>>
pub fn check_in_order<M: Checked, E>( &self, package: &PackageName, interfaces: &mut HashMap<Name, Interface>, module_files: &HashMap<Name, SourceFileId>, check: fn(package: &PackageName, interfaces: &HashMap<Name, Interface>, source: &Module) -> Outcome<M, E>, ) -> Vec<Outcome<M, E>>
Given a package name, a set of existing interfaces and a checker function, check each module in its dependencies order.
Every module is checked regardless of whether an earlier one failed, and each
comes back as one Outcome, in the order it was checked (BUG-2). Every
module the checker hands back has its Interface inserted into interfaces as
it goes, whether or not it came back with errors, so later modules keep resolving
against earlier ones: an importer of a module with an error in one declaration is
checked against the interface that module has, and reports nothing about the
import (DEC-23 decision
1).
Only an Outcome::Failed module is absent from what follows it.
module_files is how a checked module’s Interface learns the file it was
read from (Interface::file, ERR-5) — check itself is a phase-orchestrating
function and, like every phase, never knows it. This method is driver code
rather than a phase, the same as compile_package, so it is the one that can
look the id up and stamp it on before the interface goes into the shared map.
A module missing from module_files — there is none in the real pipeline,
since only a module that already parsed reaches here — simply leaves that
interface’s file as None, same as a hand-built one.
check takes package and nothing beyond it to say whether this build is
exempt from the default imports — PackageName::is_core is a function of
package alone, so a checker derives its own answer from the same package
this walker was built from rather than being handed one separately.