-
-
Notifications
You must be signed in to change notification settings - Fork 908
Fix unbound variable error when matching on const record subjects #5302
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
base: main
Are you sure you want to change the base?
Fix unbound variable error when matching on const record subjects #5302
Conversation
| ValueConstructorVariant::ModuleConstant { .. } => { | ||
| // If the variable is a constant we shadow it with the refined type. | ||
| // We cannot convert it to a local variable as that would cause the | ||
| // code generator to look for a runtime variable that doesn't exist. | ||
| let mut refined_constant = variable.clone(); | ||
| refined_constant.type_ = type_; | ||
| let _ = self.environment.scope.insert(name, refined_constant); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this specific block to allow field access of const records (like user.name) to work inside the branch, matching the current behavior for local variables.
However, I noticed that Gleam doesn't do this type refinement for constants globally:
Gleam playground
Since the fix for the runtime crash doesn't strictly require this part (we could just ignore ModuleConstant entirely here), I have two questions:
- Should I keep or remove this code?
- Should I open a separate issue about global type refinement for constants (or is the current behavior deliberate)?
| source: compiler-core/src/javascript/tests/case.rs | ||
| expression: "\npub type Wibble {\n Wibble\n Wobble(int: Int)\n}\n\nconst wibble = Wibble\n\npub fn main() {\n echo wibble\n // This 'wibble' shadows the const\n let wibble = Wobble(42)\n case wibble {\n // This matches the local variable, not the const\n Wobble(_) -> wibble\n }\n}\n" | ||
| --- | ||
| ----- SOURCE CODE | ||
|
|
||
| pub type Wibble { | ||
| Wibble | ||
| Wobble(int: Int) | ||
| } | ||
|
|
||
| const wibble = Wibble | ||
|
|
||
| pub fn main() { | ||
| echo wibble | ||
| // This 'wibble' shadows the const | ||
| let wibble = Wobble(42) | ||
| case wibble { | ||
| // This matches the local variable, not the const | ||
| Wobble(_) -> wibble | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just something of interest I noticed while testing: if a const is defined but unused, it is properly optimized out of the generated JavaScript, but it still seems to have its name reserved in the variable generator.
Gleam playground
90fd708 to
a071320
Compare
Closes #5261.