Skip to content

← Modules, Visibility, Testing and Docs step 11 of 22

Medium Framework

Module file layout: foo.rs, foo/mod.rs, and #[path]

Implement two helpers that calculate paths for a supported subset of Rust's module-file rules. They return strings; they do not open files or invoke rustc.

pub fn module_file(entry: &str, module_path: Vec<String>, style: &str) -> String
pub fn path_attr_file(containing_file: &str, inline_mods: Vec<String>, attr_path: &str) -> String

Use relative paths with / separators. File names end in .rs; module names are nonempty single path components. Paths contain no . or .. components, leading/trailing slashes or repeated separators. Preserve names and spelling; do not normalize paths or check whether files exist.

Find a module's file

module_file receives a crate's entry file, a chain of module names and one of two styles: "self_named" or "mod_rs". An empty chain returns entry unchanged. Otherwise, start in the entry file's directory and use the following layouts:

Entry Module chain Style Result
src/lib.rs ["util"] self_named src/util.rs
src/lib.rs ["util", "config"] self_named src/util/config.rs
src/lib.rs ["util", "config"] mod_rs src/util/config/mod.rs
src/bin/tool.rs ["helpers"] self_named src/bin/helpers.rs
lib.rs [] mod_rs lib.rs

The entry is a crate root even when it has a custom name such as tool.rs. These paths assume ordinary module declarations with no #[path] overrides.

In an actual project, each declaration introduces one module:

File                  Contents
src/lib.rs            mod util;
src/util.rs           mod config;
src/util/config.rs    // config's items

In the alternative layout, put the same declarations in src/lib.rs and src/util/mod.rs, with the child body in src/util/config/mod.rs. src/util.rs can coexist with a src/util/ directory containing children. A normal mod util; lookup is ambiguous if both src/util.rs and src/util/mod.rs exist. Your helper selects the requested style rather than performing that filesystem search.

Resolve a relative #[path] attribute

path_attr_file receives the file containing the declaration, its enclosing inline-module names from outermost to innermost, and the attribute's relative path. For example, mod outer { mod inner { ... } } supplies ["outer", "inner"].

This helper assumes lib.rs and main.rs are conventional crate roots, mod.rs files define directory modules, and every other file is an ordinary module whose name matches its file stem. Custom-named roots and enclosing #[path] overrides are outside this helper's scope: filenames alone cannot identify those cases.

Location of the declaration Base directory
No enclosing inline modules Containing file's directory
Inside inline modules in a root or mod.rs file Containing directory, followed by the inline names
Inside inline modules in another module file Containing directory, file stem, then inline names

Append attr_path to that base. A stem is the file name without its final .rs suffix. An empty containing directory does not add a leading slash.

Containing file Inline modules Attribute path Result
src/a/mod.rs ["inline"] other.rs src/a/inline/other.rs
src/a/b.rs ["inline"] other.rs src/a/b/inline/other.rs
src/a/b.rs [] other.rs src/a/other.rs
src/lib.rs ["x", "y"] z.rs src/x/y/z.rs

In real Rust, the attribute changes where a module's body is loaded; it does not rename the module. For example, #[path = "other.rs"] mod x; still declares a module named x.

Repair the starter

module_file currently ignores all ancestor module names. Add them to the base directory before choosing the final file name.

path_attr_file already appends inline names, but omits the extra file-stem directory for ordinary module files. Add that directory only when inline modules are present and the file is not one of the supported root/mod.rs cases.

Keep these as string calculations. The submission editor supplies one source file, so this task tests predicted paths rather than asking you to upload a multi-file Rust project. Inline mod name { ... } blocks can be used normally in submissions; an external mod name; needs a separate source file.