-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Not planned
Not planned
Copy link
Labels
A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Description
For example,
fn foo() {}
fn f1() {
fn bar() {
foo(); // This resolves to the item
}
let foo = 0;
}
fn f2() {
let foo = 0;
fn bar() {
foo(); // This is an error (cannot capture dynamic environment in a fn item)
}
}
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.
Metadata
Metadata
Assignees
Labels
A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
jseyfried commentedon Apr 20, 2016
cc @nrc @petrochenkov @nikomatsakis
petrochenkov commentedon Apr 21, 2016
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".
This can probably be done with a lint with the same success:
If such isolation of function bodies gives some nice algorithmic properties, I'd do that without hesitation.
nrc commentedon Apr 21, 2016
I think I would prefer for inner function bodies not to 'see' the enclosing function bodies at all, i.e.,
f2
in the OP would not be an error. AIUI, the motivation is only that error comparing with closures, which I believe should be a lint, rather than an error (to be clear, there should be a warning lint when there are names in scope both outside the function and inside it, which today would be an error. Obvs, if there is only a name inside the function, then it must still be an error).I believe the change is backwards compatible since it only admits more programs.
jseyfried commentedon Apr 21, 2016
@petrochenkov @nrc ok, you've convinced me that we should allow the example in the OP with a warning lint.
jseyfried commentedon Apr 22, 2016
@nrc Do you think the relative order of macro 2.0 definitions and statements in a block should matter?
For example,
jseyfried commentedon Apr 22, 2016
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?"
nikomatsakis commentedon Apr 22, 2016
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:
Right?
nikomatsakis commentedon Apr 22, 2016
In any case, I agree that -- in the original example -- the reference should resolve successfully in both cases to the
foo
at the module scope.jseyfried commentedon Apr 22, 2016
@nikomatsakis
Agreed.
Right.
I think we're all pretty much in agreement on how to handle this issue.
jseyfried commentedon Apr 25, 2016
Related question -- should this compile? (currently, it doesn't)
Since the type parameter
E
is above the function itemg
in the scope hierarchy (unlikef
's locals), we might want to considerE
to be in the scope ofg
's body.Of course, since we can't use the type parameter from
g
's body, we also might want to consider it to be not in scope. I don't have a strong opinion either way.nrc commentedon Apr 26, 2016
@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.
jseyfried commentedon Apr 26, 2016
@nrc
Sounds good, I agree. Note that this differs from today's macros, which can see the function body.
arielb1 commentedon Apr 26, 2016
@nrc
That's quite unlike Scheme macros! I think the interaction between macros and
let
is subtle enough and insufficiently-useful that we should not have it.19 remaining items