mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Generate unique symbols for shadowing identifiers
This code has a shadowing error: ``` b = False f = \b -> b f b ``` but prior to this commit, the compiler would hit an internal error during monomorphization and not even get to report the error. The reason was that when we entered the closure `\b -> b`, we would try to introduce the identifier `b` to the scope, see that it shadows an existing identifier, and not insert the identifier. But this meant that when checking the body of `\b -> b`, we would think that we captured the value `b` in the outer scope, but that's incorrect! The present patch fixes the issue by generating new symbols for shadowing identifiers, so deeper scopes pick up the correct reference. This also means in the future we may be able to compile and execute code with shadows, even though it will still be an error. Closes #2343
This commit is contained in:
parent
632d809f2a
commit
0eede1cd86
8 changed files with 67 additions and 30 deletions
|
@ -32,7 +32,7 @@ pub enum Pattern {
|
|||
Underscore,
|
||||
|
||||
// Runtime Exceptions
|
||||
Shadowed(Region, Loc<Ident>),
|
||||
Shadowed(Region, Loc<Ident>, Symbol),
|
||||
// Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments!
|
||||
UnsupportedPattern(Region),
|
||||
// parse error patterns
|
||||
|
@ -65,7 +65,7 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
|
|||
use Pattern::*;
|
||||
|
||||
match pattern {
|
||||
Identifier(symbol) => {
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
symbols.push(*symbol);
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,6 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
|
|||
| Underscore
|
||||
| MalformedPattern(_, _)
|
||||
| UnsupportedPattern(_) => {}
|
||||
|
||||
Shadowed(_, _) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,13 +119,14 @@ pub fn canonicalize_pattern<'a>(
|
|||
|
||||
Pattern::Identifier(symbol)
|
||||
}
|
||||
Err((original_region, shadow)) => {
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
shadow: shadow.clone(),
|
||||
}));
|
||||
output.references.bound_symbols.insert(new_symbol);
|
||||
|
||||
Pattern::Shadowed(original_region, shadow)
|
||||
Pattern::Shadowed(original_region, shadow, new_symbol)
|
||||
}
|
||||
},
|
||||
GlobalTag(name) => {
|
||||
|
@ -268,7 +267,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
},
|
||||
});
|
||||
}
|
||||
Err((original_region, shadow)) => {
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
shadow: shadow.clone(),
|
||||
|
@ -278,7 +277,8 @@ pub fn canonicalize_pattern<'a>(
|
|||
// are, we're definitely shadowed and will
|
||||
// get a runtime exception as soon as we
|
||||
// encounter the first bad pattern.
|
||||
opt_erroneous = Some(Pattern::Shadowed(original_region, shadow));
|
||||
opt_erroneous =
|
||||
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ pub fn canonicalize_pattern<'a>(
|
|||
},
|
||||
});
|
||||
}
|
||||
Err((original_region, shadow)) => {
|
||||
Err((original_region, shadow, new_symbol)) => {
|
||||
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
|
||||
original_region,
|
||||
shadow: shadow.clone(),
|
||||
|
@ -349,7 +349,8 @@ pub fn canonicalize_pattern<'a>(
|
|||
// are, we're definitely shadowed and will
|
||||
// get a runtime exception as soon as we
|
||||
// encounter the first bad pattern.
|
||||
opt_erroneous = Some(Pattern::Shadowed(original_region, shadow));
|
||||
opt_erroneous =
|
||||
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -452,7 +453,7 @@ fn add_bindings_from_patterns(
|
|||
use Pattern::*;
|
||||
|
||||
match pattern {
|
||||
Identifier(symbol) => {
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
answer.push((*symbol, *region));
|
||||
}
|
||||
AppliedTag {
|
||||
|
@ -477,7 +478,6 @@ fn add_bindings_from_patterns(
|
|||
| FloatLiteral(_, _, _)
|
||||
| StrLiteral(_)
|
||||
| Underscore
|
||||
| Shadowed(_, _)
|
||||
| MalformedPattern(_, _)
|
||||
| UnsupportedPattern(_) => (),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue