-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Paths involving 'super' don't work from within a function #64079
Comments
Getting this to work in a backward-compatible way is going to be tricky. struct Foo;
fn my_fn() {
use self::Foo;
}
mod bar {
fn other_fn() {
use super::Foo;
}
} The naive approach of treating functions as normal module scopes would break both of these snippets. I think this is going to require an RFC to add a new type of path qualifier. Something like I'll write up a pre-RFC and post it on internals. |
So, this is indeed a missing piece in our name resolution story. The solution I imagined is introduction of transparent modules that
This seems to be a feature with a much wider range of applications than special path syntax extensions like |
Here's an example in which we generate a module, pull selected names into it, but provide isolation from any other names in scope. fn f() {
struct FromScopeGood;
struct FromScopeBad;
#[transparent]
mod helper { // Gives access to selected names
use FromScopeGood;
mod useful { // Provides isolation from any other names
type A = super::FromScopeGood; // OK
type B = FromScopeBad; // ERROR
}
}
} |
If isolation is not specifically required, then it's better to generate |
@petrochenkov: I don't think that a In my view, the root issue here is that functions create a strange kind of scope that hides declarations from its children. I would expect the following two snippets to have equivalent behavior: struct TopLevelStruct;
mod outer {
struct OuterStruct;
mod inner {
use super::OuterStruct;
use super::super::TopLevelStruct;
}
} struct TopLevelStruct;
fn outer() {
struct OuterStruct;
fn inner() {
use super::OuterStruct;
use super::super::TopLevelStruct;
}
} However, the second snippet does not compile. Since I think it's important for this snippet of code to be able to compile: struct SomeType; // Either declared or imported one scope above 'inner'
mod inner {
use super::SomeType;
} That is, it should be possible to declare a module and import items from the scope/module immediately above the new module. This is orthogonal to any I think adding a new path qualifier is ugly, but it's the only way I can think of to preserve backwards compatibility. In a future edition, it would be possible to make functions behave like anonymous modules in terms of import resolution. That is: struct TopLevelStruct;
fn outer() {
struct OuterStruct;
fn inner() {
use super::OuterStruct;
use super::super::TopLevelStruct;
}
} would compile, but it would still be impossible to import items declared in Obviously, this would require an RFC. However, I think there's a lot of value in making |
Also, isn't a #[transparent]
mod foo {
} is the same as mod foo {
use fn::super::*;
} |
I'll close this as not-a-bug / RFC material. |
The following code compiles correctly:
However, when wrapped in a function:
it gives the following error:
This can make it difficult to write attribute macros which expand to module declarations. Ideally, such macros would be useeable no matter where the annotated type is declared. However, this issue prevents such macros from being used on a type declared within a function.
The text was updated successfully, but these errors were encountered: