Yes, and my belief is that that goal is an anti-goal. After all, you can program without function parameters, using static
items for everything instead, and indeed, I've worked on systems where that was the norm (not in Rust). But it leads to hard-to-maintain code, because you break local reasoning; there's information being smuggled around out of sight of function parameters.
I would prefer to see the "no need for foo
to explicitly know what context items bar
and baz
require" filled by a means to say "foo
's context parameter is bar
's needed context + baz
's needed context". Opening up some syntax for bikeshedding, you'd put the context after the where
clause in a using
clause, and be able to write something like:
fn foo(a: Random, b: Parameters, c: Here) using bar() {
…
}
fn bar(a: More, b: Random, c: Parameters) using
mut Cx1: Vec<Foo>,
baz(),
{
…
}
fn baz<'a>(g: Wow, h: Even, i: More) -> &'a Cx3
using
mut Cx3: Vec<Baz> + 'a,
mut Cx2: Vec<Bar>,
{
…
}
In this bikesheddable version, foo
declares in its signature that bar
's context is in play, but that it's opaque to foo
(so I know that foo
itself doesn't touch any part of the context, but does need a context set up for bar
).
In turn, bar
declares that it uses Cx1
from the context, and that Cx1
is a Vec<Foo>
; it also needs all of baz
's context available for passing through. And baz
declares that it uses Cx3
and Cx2
from context, but nothing more.
I can also see from baz
's signature that the lifetime 'a
is related to Cx3
somehow. And, in this model, if baz
needs read-only access to Cx1
now, its signature would change:
fn baz<'a>(g: Wow, h: Even, i: More) -> &'a Cx3
using
Cx1: Vec<Foo>,
mut Cx3: Vec<Baz> + 'a,
mut Cx2: Vec<Bar>,
This tells me that it can read Cx1
- and because of the baz()
syntax in bar
's declared context needs, it automatically picks up this requirement, even if baz
didn't already need Cx1
.
Also note in here that foo
declares that it does not touch the context - it just passes through enough to be able to call bar
. bar
declares that it can modify Cx1
, and passes through what baz
needs. The modified baz
says it reads Cx1
, and modifies Cx3
and Cx2
.