error[E0425]: cannot find function `local_function` in this scope
--> src/main.rs:9:9
|
9 | local_function();
| ^^^^^^^^^^^^^^ not found in this scope
This seemed a bit odd to me as the function is right there, in the scope of the impl block of MyStruct. It's simple enough to fix by moving the function out of the impl block but I don't want to move it so far away from where it is used. Or call it with MyStruct::local_function()but that is adding noise.
To me it seems similar to the situation of defining an inner function within the scope of a function like so:
Notice that the code is not similar: the function is defined inside the other function, so it really has the same scope.
I think you can simply think that impl is only a way to provide a "namespace" to methods. To say they belong to a structure. So you can use Self::thefunction, of x.the_method() if it references &self.
But when naively looking at things within curly braces, within curly braces, within curly braces... it still seems somewhat odd. For example compare to this:
Here the version of f2() inside f1() is what gets run. To my mind:
the fn f1() { is analogus to the impl block,
the fn f2() and fn f3() are analgus to my local_function() and method_1() above,
and the call f3() finds it without any extra help to resolve things.
Yeah, it is unfortunate the Name resolution and Scopes chapters of the reference aren't written yet. The closest thing to documentation on how name resolution works in different kind of scopes is the developer guide, which states (emphasis by me):
A name is visible only in certain area in the source code. This forms a hierarchical structure, but not necessarily a simple one ‒ if one scope is part of another, it doesn't mean the name visible in the outer one is also visible in the inner one, or that it refers to the same thing.
So basically the only answer I can give you based on the documentation I could find: name resolution is complicated.
I think the best way to think about this is that an impl is a very special thing in multiple ways. In particular, it isn't a scope for items; it never matters to name lookup whether two items are in the same impl or separate impls. Everything you declare in an impl gets associated with the specified type instead of participating in lexical scope. And if the impl is a trait implementation, then you can't even put arbitrary items in it at all.
// module scope for items
impl Foo {
// not a scope (except for generics on the impl)
fn bar() {
// new scope for variables and items