mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
prevent duplicate definitions
patterns that bind multiple symbols, like `{ x, y } = someDef` would insert the definition twice (once for x, once for y). that can lead to problems in codegen, and means the work for this definition is done twice. Now we use the region of the pattern as a key, to ensure the pattern and its associated expression is only processed once.
This commit is contained in:
parent
ceba17ed98
commit
e5a9a016cd
3 changed files with 19 additions and 4 deletions
|
@ -418,6 +418,15 @@ fn group_to_declaration(
|
|||
result
|
||||
};
|
||||
|
||||
// patterns like
|
||||
//
|
||||
// { x, y } = someDef
|
||||
//
|
||||
// Can Bind multiple symbols, when not incorrectly recursive (which is guaranteed in this function)
|
||||
// normally `someDef` would be inserted twice. We use the region of the pattern as a unique key
|
||||
// for a definition, so every definition is only inserted (thus typechecked, code-gen'd) once
|
||||
let mut seen_pattern_regions: ImSet<Region> = ImSet::default();
|
||||
|
||||
for cycle in strongly_connected_components(&group, filtered_successors) {
|
||||
if cycle.len() == 1 {
|
||||
let symbol = &cycle[0];
|
||||
|
@ -433,7 +442,10 @@ fn group_to_declaration(
|
|||
new_def.loc_expr.value = Closure(fn_var, name, recursion, args, body);
|
||||
}
|
||||
|
||||
declarations.push(Declare(new_def));
|
||||
if !seen_pattern_regions.contains(&new_def.loc_pattern.region) {
|
||||
declarations.push(Declare(new_def.clone()));
|
||||
}
|
||||
seen_pattern_regions.insert(new_def.loc_pattern.region);
|
||||
}
|
||||
} else {
|
||||
// Topological sort gives us the reverse of the sorting we want!
|
||||
|
@ -451,7 +463,10 @@ fn group_to_declaration(
|
|||
new_def.loc_expr.value = Closure(fn_var, name, recursion, args, body);
|
||||
}
|
||||
|
||||
can_defs.push(new_def);
|
||||
if !seen_pattern_regions.contains(&new_def.loc_pattern.region) {
|
||||
can_defs.push(new_def.clone());
|
||||
}
|
||||
seen_pattern_regions.insert(new_def.loc_pattern.region);
|
||||
}
|
||||
}
|
||||
declarations.push(DeclareRec(can_defs));
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
|||
/// TODO replace Located with this
|
||||
pub type Loc<T> = Located<T>;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct Region {
|
||||
pub start_line: u32,
|
||||
pub end_line: u32,
|
||||
|
|
|
@ -25,7 +25,7 @@ mod test_infer {
|
|||
// and variables actually used in constraints
|
||||
let (declared, used) = roc::types::variable_usage(&constraint);
|
||||
|
||||
if false && declared.flex_vars.len() + declared.rigid_vars.len() != used.len() {
|
||||
if declared.flex_vars.len() + declared.rigid_vars.len() != used.len() {
|
||||
dbg!(&constraint);
|
||||
dbg!(expr);
|
||||
println!("VARIABLE USAGE PROBLEM");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue