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

Add "mea culpa" to foreign module assignment error. #56956

Merged
merged 1 commit into from
Jan 6, 2025
Merged

Conversation

Keno
Copy link
Member

@Keno Keno commented Jan 5, 2025

As requested in #56933, acknowledge that this error was missing in Julia 1.9 and 1.10 and provide a reference to the issue so that people have an easier starting point.

@giordano
Copy link
Contributor

giordano commented Jan 5, 2025

Should this be backported to v1.11?

@Keno Keno added the backport 1.11 Change should be backported to release-1.11 label Jan 5, 2025
@Keno
Copy link
Member Author

Keno commented Jan 5, 2025

Yes, you beat me to it ;).

src/module.c Outdated
Comment on lines 293 to 295
jl_errorf("Global %s.%s does not exist and cannot be assigned.\n"
"Note: Julia 1.9 and 1.10 inadvertently omitted this error check (#56933).\n"
"Hint: Declare it using `global` before attempting assignment.", jl_symbol_name(m->name), jl_symbol_name(var));
Copy link
Member

@MilesCranmer MilesCranmer Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
jl_errorf("Global %s.%s does not exist and cannot be assigned.\n"
"Note: Julia 1.9 and 1.10 inadvertently omitted this error check (#56933).\n"
"Hint: Declare it using `global` before attempting assignment.", jl_symbol_name(m->name), jl_symbol_name(var));
jl_errorf("Global %s.%s does not exist and cannot be assigned.\n"
"Note: Julia 1.9 and 1.10 inadvertently omitted this error check, meaning it was possible to write `{module}.{var} = {value}` without a preceding `:global`.\n"
"Hint: Declare it using `global` before attempting assignment:\n"
" ```\n"
" %s.eval(Expr(:global, :%s)\n"
" %s.%s = ...\n"
" ```",
jl_symbol_name(m->name), jl_symbol_name(var),
jl_symbol_name(m->name), jl_symbol_name(var),
jl_symbol_name(m->name), jl_symbol_name(var));

Copy link
Member

@MilesCranmer MilesCranmer Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just to clarify things, as when I first tried this I thought I could do

global A.x

based on the error message, before realising I needed to evaluate global inside A.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My primary concern with being too explicit here is that there are other paths that reach this error, not just the frontend syntax, so if you reach it through one of those paths, that error will be confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think my issue needs to be linked in the error though. Just something to:

  1. Help people update their code (the "declare using global" should be more precise), and
  2. Let them know that this syntax used to work, it wasn't their imagination or mistake

Copy link
Member Author

@Keno Keno Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about Hint: Declare it using `global %s` inside `%s` before attempting assignment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular f() = (Main.x = 1) and f() = (global x = 1) are not equivalent, because Main could be redefined later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I’m just trying to figure out how to use the exact mechanism the REPL uses for this. Because then we can just use that inside PythonCall to communicate new globals.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you write x = 1, the REPL does the moral equivalent of Core.eval(Main, :(x = 1)). Since there's no Main., the global gets introduced automatically at definition time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling Core.eval(::Module, Expr(:global, sym)) should be perfectly fine here though, as there isn't any opportunity to optimize this code anyways (it is python), and is what x=1 expands to normally. As Keno mentioned, we should add a builtin too (similar to setglobal, there should be a declareglobal and declareconst functions), so that you don't need the awkward eval form for them, but that is merely a difference in spelling of the operation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for the detailed discussion on this.

As requested in #56933, acknowledge that this error was missing in Julia 1.9 and 1.10
and provide a reference to the issue so that people have an easier starting point.
@Keno Keno merged commit ad5533c into master Jan 6, 2025
7 checks passed
@Keno Keno deleted the kf/meaculpa branch January 6, 2025 21:28
@KristofferC KristofferC mentioned this pull request Jan 28, 2025
38 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport 1.11 Change should be backported to release-1.11
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants