Skip to content
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

UndefVarError if trying to shadow global variable using let #50369

Closed
jonas-schulze opened this issue Jun 30, 2023 · 4 comments · Fixed by #51979
Closed

UndefVarError if trying to shadow global variable using let #50369

jonas-schulze opened this issue Jun 30, 2023 · 4 comments · Fixed by #51979
Labels
feature Indicates new feature / enhancement requests

Comments

@jonas-schulze
Copy link
Contributor

When working with Pluto, I like to wrap more complex cells using let and reuse simple variable names.
Within Pluto, everything works fine, but when executing the notebook as a standalone script, Julia complains about some variables not being defined.

MWE

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.9.1 (2023-06-07)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> x = 5
5

julia> y = let
           x = 2x
           x += 1
       end
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] top-level scope
   @ REPL[2]:2

Workaround

By removing the initial line break, Julia gets what I mean.
But I think this is a bug of Julia (and I don't want to use different variable names or edit the whole already-too-long notebook). 🙃

julia> y = let x = 2x
           x += 1
       end
11

julia> x
5
@MasonProtter
Copy link
Contributor

MasonProtter commented Jun 30, 2023

No I don't think this is considered a bug, this is a core part of how name resolution works in julia. When you write

let ex1 = ex2
...
end

ex1 is meant to be resolved in the local scope of the let block, but the right hand side, ex2 is resolved in the outer scope. It's by design that if instead you write

let 
    ex1 = ex2
end

that both ex1 and ex2 are resolved in the local scope. If you have an assignment to x in the local scope, then it's assumed now that x is referring to a local variable instead of the global variable.

@jonas-schulze
Copy link
Contributor Author

jonas-schulze commented Jun 30, 2023

During definition of x, an rvalue of the same name obviously refers to the global identifier. By your logic, not even ex2 would exist.

Similarly, even the following continuation of my example would be illegal, which it is clearly not.

let
    y = 2x
end

@jonas-schulze jonas-schulze reopened this Jun 30, 2023
@KristofferC
Copy link
Member

No, because x is not a local variable in that example.

@MasonProtter
Copy link
Contributor

I think the behaviour being requested would be a somewhat reasonable thing for us to do, and I think it’s fine to keep the issue open as a feature request.

My point was just that it’s not really a bug. as far as I’m aware this is understood and intended behaviour.

@brenhinkeller brenhinkeller added the feature Indicates new feature / enhancement requests label Aug 4, 2023
vtjnash added a commit that referenced this issue Oct 31, 2023
Record the 'scope' of the variable that was undefined (the Module, or a
descriptive word such as :local or :static_parameter). Add that scope to
the error message, and expand the hint suggestions added by the REPL to
include more specific advice on common mistakes:

  - forgetting to set an initial value
  - forgetting to import a global
  - creating a local of the same name as a global
  - not matching a static parameter in a signature subtype

Fixes #17062 (although more could probably be done to search for typos using REPL.string_distance and getting the method from stacktrace)
Fixes #18877
Fixes #25263
Fixes #35126
Fixes #39280
Fixes #41728
Fixes #48731
Fixes #49917
Fixes #50369
vtjnash added a commit that referenced this issue Nov 8, 2023
Record the 'scope' of the variable that was undefined (the Module, or a
descriptive word such as :local or :static_parameter). Add that scope to
the error message, and expand the hint suggestions added by the REPL to
include more specific advice on common mistakes:

  - forgetting to set an initial value
  - forgetting to import a global
  - creating a local of the same name as a global
  - not matching a static parameter in a signature subtype

Fixes #17062 (although more could probably be done to search for typos using REPL.string_distance and getting the method from stacktrace)
Fixes #18877
Fixes #25263
Fixes #35126
Fixes #39280
Fixes #41728
Fixes #48731
Fixes #49917
Fixes #50369
@vtjnash vtjnash closed this as completed in 449c7a2 Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Indicates new feature / enhancement requests
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants