cap_ceiling: a module uses a capability its needs lines do not declare
Each module declares, with needs, the capabilities its code may use. This
error reports a module whose code (a function body, or a module-level let)
reaches a capability above that ceiling, here a nested module whose parent
declares the capability but which does not. The code carries the capability
after a colon (cap_ceiling:IO.FileRead), and the fix inserts the missing
needs line. When cap_needs reports the same gap at the call, only that error is
shown.
A program that triggers it
mod Main do
needs IO.Console
needs IO.FileRead
mod Config do
needs IO.Console
fn motd() : String do
match File.read("/etc/motd") do
Ok(s) -> s
Err(_) -> ""
end
end
end
fn main(_c : Cap(IO.Console), _r : Cap(IO.FileRead)) do
println(Config.motd())
end
end
The fix
Declare the capability in the module whose code uses it. The outer module’s
needs IO.FileRead does not cover Config: each module declares its own.
mod Main do
needs IO.Console
needs IO.FileRead
mod Config do
needs IO.Console
needs IO.FileRead
fn motd() : String do
match File.read("/etc/motd") do
Ok(s) -> s
Err(_) -> ""
end
end
end
fn main(_c : Cap(IO.Console), _r : Cap(IO.FileRead)) do
println(Config.motd())
end
end
Why the rule exists
A module’s header is its declaration of authority: a reviewer can read the
needs lines and know every capability its code can exercise without reading
the bodies. Code that exceeds them would make the header a lie.
See also: the language reference.