-
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
resolve: the relative order of items and statements in a block can be important #33118
Comments
My intuition says that function bodies (and constant initializers, etc) should be isolated from local variables in their containing scopes. I suppose that current behavior is targeted at people coming from languages that allow nested functions to capture their environment, so they can get proper diagnostics - "you can't do that in Rust".
If such isolation of function bodies gives some nice algorithmic properties, I'd do that without hesitation. |
I think I would prefer for inner function bodies not to 'see' the enclosing function bodies at all, i.e., I believe the change is backwards compatible since it only admits more programs. |
@petrochenkov @nrc ok, you've convinced me that we should allow the example in the OP with a warning lint. |
@nrc Do you think the relative order of macro 2.0 definitions and statements in a block should matter? fn foo() {}
fn f1() {
macro_rules_v2! bar { () => { foo() } }
let foo = 0;
bar!(); // `foo` in this expansion would resolve to the item
}
fn f2() {
let foo = 0;
macro_rules_v2! bar { () => { foo() } }
bar!(); // Should `foo` in this expansion resolve to the item or the local?
} |
If we decided the relative order of macro 2.0 definitions and statements should not matter, we would be able to use a macro in a statement before it was defined in the statement. Perhaps a simpler way to state the question is "should a macro 2.0 definition in a block be analogous to a function item or to a local variable initialized with a closure?" |
A couple of points:
Maybe I am unusual, but this error always confuses me every time I get it. It assumes (as @petrochenkov said) that I was trying to capture that variable in the first place, but -- because I know Rust's rules -- I never am. I would much prefer a straight-forward error with a HELP attached or something like that. Just to clarify though, there are two distinct cases to be concerned about:
The example targets case 1, but I just want to be clear that consider this distinct from case 2: fn bar() {
let x = foo; // resolves to the inner fn `foo`
let foo = 22;
let y = foo; // resolves to the variable
fn foo() { }
} Right? |
In any case, I agree that -- in the original example -- the reference should resolve successfully in both cases to the |
Agreed.
Right. I think we're all pretty much in agreement on how to handle this issue. |
Related question -- should this compile? (currently, it doesn't) enum E { V }
fn f<E>(_: E) {
fn g() {
let _ = E::V; // is the type parameter `E` in scope here? (currently, it is)
}
} Since the type parameter Of course, since we can't use the type parameter from |
@jseyfried well, we get into hygiene questions, but assuming we're only talking about stuff visible due to the definition (i.e., default hygiene rules), then I think macros should follow the same rules as functions, i.e., they don't 'see' the function body at all. |
Sounds good, I agree. Note that this differs from today's macros, which can see the function body. |
That's quite unlike Scheme macros! I think the interaction between macros and |
I'm not aware of exactly how Scheme macros work here. I think I am proposing that there should not be interaction between macro definitions and |
We have to be careful about backwards compatibility here.
|
The current plan is to implement a new, backwards incompatible " |
I see, I thought that we were talking about the interaction of today's macros with |
I wanted identifiers in syntactically unambiguous contexts to always be interpreted as fresh bindings, i.e.
but this issue needs to be fixed first because together they can result in some ridiculous behavior:
|
…nkov Disallow shadowing const parameters This pull request fixes rust-lang#85348. Trying to shadow a `const` parameter as follows: ```rust fn foo<const N: i32>() { let N @ _ = 0; } ``` currently causes an ICE. With my changes, I get: ``` error[E0530]: let bindings cannot shadow const parameters --> test.rs:2:9 | 1 | fn foo<const N: i32>() { | - the const parameter `N` is defined here 2 | let N @ _ = 0; | ^ cannot be named the same as a const parameter error: aborting due to previous error ``` This is the same error you get when trying to shadow a constant: ```rust const N: i32 = 0; let N @ _ = 0; ``` ``` error[E0530]: let bindings cannot shadow constants --> src/lib.rs:3:5 | 2 | const N: i32 = 0; | ----------------- the constant `N` is defined here 3 | let N @ _ = 0; | ^ cannot be named the same as a constant error: aborting due to previous error ``` The reason for disallowing shadowing in both cases is described [here](rust-lang#33118 (comment)) (the comment there only talks about constants, but the same reasoning applies to `const` parameters).
Triage: A PR looking into fixing this issue was closed with the motivation that the current behavior should be kept unchanged after all. Let's also close this issue. |
For example,
Since items in a block are above the block's local variables in the scope hierarchy, it might make sense to resolve the items' bodies in scopes that descend directly from the scope of the block's items, bypassing the scopes of the local variables.
That being said, I think I prefer the current behavior.However, since it will mildly complicate name resolution in the future, I wanted to make sure that we actually want this behavior.The text was updated successfully, but these errors were encountered: