-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot refer to item inside function from module inside function #79260
Comments
(If the lang team agrees that this code should compile, I'm willing to attempt a patch to fix.) |
Note that fixing this would break this code: fn main() {
mod foo {
use super::*;
fn foobar() {
bar();
}
}
}
fn bar() {} |
I'm not convinced it would break that code; |
I can find another example of this which is easy to reproduce and seems like a much more likely case to trigger! Write a doctest which declares a module inside it: /// ```rust
/// struct Foo;
///
/// mod foobar {
/// use super::*;
///
/// fn bar() -> Foo { Foo }
/// }
///
/// ```
fn foo() {} This doctest will fail to compile:
I would guess that the doctest framework wraps the doctest code inside a function, so we see exactly the same issue as in my original report. |
Ah, but I think this variation of @jonas-schievink 's example will break: fn main() {
mod foo {
use super::*;
fn foobar() {
bar();
}
}
fn bar() {
println!("inner bar");
}
}
fn bar() {
println!("outer bar");
} At the moment it always prints (We could perhaps make it backwards compatble by letting items outside the function take precedence, and then switch the order to prefer items inside the function on an edition change.) |
I am against changing the meaning of I also wouldn't call this a bug. Everything is working as it originally is intended to. IMO, if you need a module, just like if you need an impl, it should not be defined in a function. |
We probably need some way to refer to block-that-are-parent-of-modules, but Besides being a breaking change, path resolving to an unnamed block is some new possibility that will cause a number of subsequent issues. use super as foo; // referes to a block
let bar = foo; |
My preferred solution to this issue is probably UPD: Example. struct S;
#[transparent]
mod m {
fn f() {
let s = S; // OK
}
} |
I wrote a PR to experiment with what I proposed above (#79309) - I've added an alternatives section with |
I would like to see this result: 1. For Rust before 2024 edition fn main() {
mod foo {
use super::*;
fn foobar() {
bar(); // <- error[E0425]: cannot find function `bar` in this scope
}
}
fn bar() {
println!("inner bar");
}
}
2. For Rust before 2024 edition fn main() {
mod foo {
use super::*;
fn foobar() {
bar();
}
}
fn bar() {
println!("inner bar");
}
}
fn bar() {
println!("outer bar");
}
3. For Rust before 2024 edition fn main() {
#[enable_fn_scope_from_inner_module] // <- !!!
mod foo {
use super::*;
fn foobar() {
bar();
}
}
fn bar() {
println!("inner bar");
}
}
fn bar() {
println!("outer bar");
}
4. For Rust before 2024 edition #![enable_fn_scope_from_inner_module] // <- !!!
fn main() {
mod foo {
use super::*;
fn foobar() {
bar();
}
}
fn bar() {
println!("inner bar");
}
}
fn bar() {
println!("outer bar");
}
5. For Rust 2024 edition fn main() {
mod foo {
use super::*;
fn foobar() {
bar();
}
}
fn bar() { // <- obscures the outer bar
println!("inner bar");
}
}
fn bar() {
println!("outer bar");
}
|
Alternatively, for this non-working example: we can use this: However, there were difficulties with rust-analyzer: rust-lang/rust-analyzer#15805 |
Here is a real use case for this. I'd like to generate a child module in a proc macro where I'd place the definition of the builder stuct (for privacy of its fields). The builder's fields should reference types from the surrounding scope. fn example() {
struct Password(String);
// Suppose a `#[builder]` proc macro was placed on this struct
struct User {
password: Password,
}
// This module is generated by the proc-macro
mod user_builder {
use super::*;
pub(super) struct UserBuilder {
password: Option<Password>,
}
}
} I made an article about this problem here: https://elastio.github.io/bon/blog/the-weird-of-function-local-types-in-rust |
I tried this code (https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8c1861ee7e07799c5897f37f0aa2f849):
This fails to compile:
rustc --version --verbose
:Also reproduces on current nightly (as of 2020-11-21).
I suspect that what's going on is that
use super::*
doesn't actually resolve to the scope insidefn main
, but instead the surrounding scopefn main
is itself in.I tried to search around other issues to find whether this is expected.
This is a super weird special case. It seems plausible (at least to me) that
use super::*
from a module inside a function should bring other items local to that function into scope.The text was updated successfully, but these errors were encountered: