Pybites Logo Rust Platform

Use and Paths

Medium +3 pts

🎯 In Python, you bring names into scope with import and from ... import:

import math
from collections import Counter, defaultdict
from os.path import join as path_join

Rust's use statement works the same way — it brings items from other modules into the current scope so you don't have to write full paths everywhere.

Path types

Rust has three ways to reference items in the module tree:

crate:: — absolute path from the crate root (like Python's absolute imports):

use crate::utils::helpers::format_name;

super:: — relative path to the parent module (like Python's from .. import):

mod child {
    use super::parent_function;  // import from parent module
}

self:: — relative path from the current module (rarely needed, explicit):

use self::submodule::helper;

In Python, absolute imports (from mypackage.module import func) and relative imports (from ..module import func) serve the same purpose. Rust's crate:: and super:: are the equivalents.

Use patterns

Rust supports several import styles, all familiar from Python:

// Single item (like: from collections import HashMap)
use std::collections::HashMap;

// Multiple items (like: from collections import Counter, defaultdict)
use std::collections::{HashMap, HashSet};

// Glob import (like: from collections import *)
use std::collections::*;  // use sparingly

// Rename (like: from os.path import join as path_join)
use std::fmt::Result as FmtResult;

The grouped import {HashMap, HashSet} is especially handy — it avoids repeating the path prefix. Python's equivalent is separate from lines.

pub use — re-exporting

This is something Python doesn't have a direct equivalent for. pub use imports an item and makes it available to users of your module:

mod internal {
    pub fn helper() -> i32 { 42 }
}

pub use internal::helper;  // users can now call crate::helper() directly

This is like defining helper in Python's __init__.py — you're creating a public-facing API that's organized differently from the internal structure. Users see a clean API; you keep the implementation organized however makes sense internally.

pub use is common in Rust libraries: the internal module tree might be deep and organized by implementation concerns, but pub use creates a flat, convenient public API.

super:: for cross-module imports

When one module needs types from a sibling module, it reaches through the parent with super:::

mod models {
    pub struct User { pub name: String }
}

mod services {
    use super::models::User;  // import sibling's type through parent

    pub fn greet(user: &User) -> String {
        format!("Hello, {}!", user.name)
    }
}

super means "go up one level in the module tree." In the sibling-module pattern above, use super::models::User is like Python's from .models import User — reaching a sibling through the parent.

Login to see the full task and start coding.

This is a premium exercise

Log in to unlock the full exercise and start coding.

Login to access this exercise