We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Modules, Visibility, Testing and Docs step 4 of 22
Restricted visibility: pub(crate), pub(super), pub(in path)
pub and private are the two everybody learns. Real Rust codebases are held
together by the three in between.
pub(crate) // visible anywhere in this crate, nowhere outside it
pub(super) // visible from the parent module and everything under it
pub(in crate::a::b) // visible from crate::a::b and everything under it
The Book barely mentions pub(crate), and it is probably the single most useful
visibility a beginner can learn: it says “this is shared infrastructure, not
part of my public API”, which is a distinction pub cannot express.
The task
Write the oracle.
pub fn visible_from(items: Vec<(String, String)>, viewer: String, target: String) -> bool
items describes a whole crate: every entry is a (path, visibility) pair, and
modules are entries too — that is the point. viewer is the module doing
the looking, target the item being looked at. Visibilities are the strings
"private", "pub", "pub(crate)", "pub(super)" and
"pub(in crate::a::b)". An unknown target is false, not a panic.
Both privacy rules have to be implemented, including the descendant clause:
A public item is accessible from
monly if every ancestor module of it is also accessible fromm.A private item is accessible from its declaring module and all of its descendants.
So you walk the chain from the item up to the crate root and ask, at every link, whether that link admits the viewer. One private module anywhere on the chain and nothing below it can be named from outside.
The trap, and it is a good one
pub(super) on an item inside a top-level module is effectively
crate-visible. Learners read pub(super) as “only my parent can see this” and
it is not what it says.
Work it through. secret is declared in crate::a, so super is crate — the
crate root. pub(in crate) means “visible from crate and all of its
descendants”, and every module in the crate is a descendant of the crate root.
So crate::b::c can see it. The restriction restricted nothing.
pub(super) only narrows anything at depth two or more. This is not a quirk to
memorise; it falls straight out of “visibility is reachability in a tree”, which
is why implementing the oracle teaches it better than reading about it.
pub(in path) and E0742
The path in pub(in …) must name an ancestor of the item’s own module.
pub(in crate::unrelated) is E0742 — visibilities can only be restricted to
ancestor modules. You cannot hand a capability sideways; visibility is a
prefix of the tree, not an access-control list. Your inputs are always
well-formed in that respect.
Two clippy lints that flatly contradict each other
-
clippy::pub_with_shorthandwants you to writepub(super). -
clippy::pub_without_shorthandwants you to writepub(in super).
Both are restriction lints, both are off by default, and enabling both is incoherent. They are in the list on purpose: clippy has opinions, curated by teams with policies, not truths handed down from the language. When a lint tells you to change something, the question is always “do I agree”, not “how do I comply”.
One more, clippy::redundant_pub_crate: pub(crate) inside a module that is
already private is redundant, and the lint says so. It is a nursery lint, so it
is off here, but the observation is sound and worth internalising.
A caveat about this harness
Your submission is one file and therefore one crate, and it produces a binary,
not a library. Inside a single crate pub and pub(crate) are almost
interchangeable as far as compiling goes — the difference only shows up when
somebody outside the crate tries to use your code, which cannot happen here.
That is precisely why this item is an oracle problem rather than a “make it
compile” problem. The rules are real; the only way to exercise them on one file
is to implement them.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.