Skip to content

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

Easy Primitives

Build a module tree and inspect its paths

Build an inline module tree and report its module paths:

pub fn module_paths() -> Vec<String>
pub fn fn_local_path() -> String

Complete these three parts of the starter:

  1. Add pub mod planar inside geometry::area.
  2. Make strip_crate remove the crate-name prefix through the first ::. If no separator exists, return an empty string.
  3. Declare mod hidden inside the body of fn_local_path, then return its path after removing the crate prefix.

Each of the four modules must contain this function:

pub fn here() -> &'static str { module_path!() }

Use the macro to obtain the paths rather than hard-coding the expected output. The two public functions return:

Function Result
module_paths() ["geometry", "geometry::area", "geometry::area::planar"]
fn_local_path() "hidden"

module_paths explicitly collects three calls in that order. It does not discover or enumerate every module in the crate.

Declarations create the module hierarchy

mod geometry { ... } declares a module whose body is inline. Placing mod area { ... } inside it creates a child module. The declarations can all live in one source file, as they do in this exercise.

An external declaration such as mod geometry; instead loads the body from a file. Adding an arbitrary file to a source directory does not automatically make it a child module. Crate roots and mechanisms such as include! are separate ways source can enter a compilation; do not infer the entire module tree just from directory names.

See module file layout for the file-loading rules. Use inline modules for this exercise.

Remove the crate prefix

module_path!() expands to a string literal describing the module where it appears. Its first segment is the crate name. For a crate named demo, the innermost here() returns "demo::geometry::area::planar".

Remove only the first segment so the answer does not depend on the build's crate name. split_once("::") separates that prefix from the rest while preserving all later separators. The helper's no-separator case represents a path consisting only of the crate name.

A crate name can be configured by build tools or a compiler option. Do not assume it always equals the source file's name.

A module declared inside a function

A module can be declared inside a function body. Its name is available within that block, but is not introduced as a directly addressable module at the enclosing module level.

In this exercise, module_path!() inside hidden produces "demo::hidden" when the crate is named demo. It omits the enclosing function name. That string does not make crate::hidden::here() callable from outside the function: the declaration remains local to its block.

If the enclosing function were itself inside another module, that module's name would still appear. Function-local modules do not universally have a crate-root-only prefix. Nor should these strings be treated as unique item identifiers: distinct block-local declarations can produce the same text.

Read the compiler's specific complaint

The starter calls geometry::area::planar::here() before planar exists, producing an unresolved-path error. Add the missing module in the correct parent. A private item can produce a different diagnostic, such as E0603; error codes are clues to inspect the named path, not a complete classification of every possible module mistake.

Ordinary item declarations such as functions and modules can be used before their textual definitions within their scope. You do not need to move geometry above a caller just to make lookup work. macro_rules! has its own scoping rules, covered in the macro-scoping lesson.

Finally, keep all required here() functions used by the task. An unused helper can produce a dead_code warning, but making it more visible is not automatically the right fix. Remove accidental unused code or use it as intended; intentional unused code may warrant a narrowly scoped lint allowance in other projects. Choose visibility for the API you need.