mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
remove clones in most cases in can/def
This commit is contained in:
parent
80956061dd
commit
5e48577d29
1 changed files with 95 additions and 58 deletions
|
@ -864,6 +864,32 @@ fn pattern_to_vars_by_symbol(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn single_typed_can_def(
|
||||||
|
loc_can_pattern: Loc<Pattern>,
|
||||||
|
loc_can_expr: Loc<Expr>,
|
||||||
|
expr_var: Variable,
|
||||||
|
loc_annotation: Loc<crate::annotation::Annotation>,
|
||||||
|
pattern_vars: SendMap<Symbol, Variable>,
|
||||||
|
) -> Def {
|
||||||
|
let def_annotation = Annotation {
|
||||||
|
signature: loc_annotation.value.typ,
|
||||||
|
introduced_variables: loc_annotation.value.introduced_variables,
|
||||||
|
aliases: loc_annotation.value.aliases,
|
||||||
|
region: loc_annotation.region,
|
||||||
|
};
|
||||||
|
|
||||||
|
Def {
|
||||||
|
expr_var,
|
||||||
|
loc_pattern: loc_can_pattern,
|
||||||
|
loc_expr: Loc {
|
||||||
|
region: loc_can_expr.region,
|
||||||
|
value: loc_can_expr.value,
|
||||||
|
},
|
||||||
|
pattern_vars,
|
||||||
|
annotation: Some(def_annotation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO trim down these arguments!
|
// TODO trim down these arguments!
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
|
@ -1003,13 +1029,11 @@ fn canonicalize_pending_def<'a>(
|
||||||
canonicalize_annotation(env, scope, &loc_ann.value, loc_ann.region, var_store);
|
canonicalize_annotation(env, scope, &loc_ann.value, loc_ann.region, var_store);
|
||||||
|
|
||||||
// Record all the annotation's references in output.references.lookups
|
// Record all the annotation's references in output.references.lookups
|
||||||
for symbol in ann.references {
|
for symbol in ann.references.iter() {
|
||||||
output.references.lookups.insert(symbol);
|
output.references.lookups.insert(*symbol);
|
||||||
output.references.referenced_type_defs.insert(symbol);
|
output.references.referenced_type_defs.insert(*symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
let typ = ann.typ;
|
|
||||||
|
|
||||||
for (symbol, alias) in ann.aliases.clone() {
|
for (symbol, alias) in ann.aliases.clone() {
|
||||||
aliases.insert(symbol, alias);
|
aliases.insert(symbol, alias);
|
||||||
}
|
}
|
||||||
|
@ -1041,9 +1065,6 @@ fn canonicalize_pending_def<'a>(
|
||||||
// reset the tailcallable_symbol
|
// reset the tailcallable_symbol
|
||||||
env.tailcallable_symbol = outer_identifier;
|
env.tailcallable_symbol = outer_identifier;
|
||||||
|
|
||||||
// see below: a closure needs a fresh References!
|
|
||||||
let mut is_closure = false;
|
|
||||||
|
|
||||||
// First, make sure we are actually assigning an identifier instead of (for example) a tag.
|
// First, make sure we are actually assigning an identifier instead of (for example) a tag.
|
||||||
//
|
//
|
||||||
// If we're assigning (UserId userId) = ... then this is certainly not a closure declaration,
|
// If we're assigning (UserId userId) = ... then this is certainly not a closure declaration,
|
||||||
|
@ -1051,7 +1072,6 @@ fn canonicalize_pending_def<'a>(
|
||||||
//
|
//
|
||||||
// Only defs of the form (foo = ...) can be closure declarations or self tail calls.
|
// Only defs of the form (foo = ...) can be closure declarations or self tail calls.
|
||||||
if let (
|
if let (
|
||||||
&ast::Pattern::Identifier(_name),
|
|
||||||
&Pattern::Identifier(ref defined_symbol),
|
&Pattern::Identifier(ref defined_symbol),
|
||||||
&Closure(ClosureData {
|
&Closure(ClosureData {
|
||||||
function_type,
|
function_type,
|
||||||
|
@ -1064,13 +1084,8 @@ fn canonicalize_pending_def<'a>(
|
||||||
ref captured_symbols,
|
ref captured_symbols,
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
) = (
|
) = (&loc_can_pattern.value, &loc_can_expr.value)
|
||||||
&loc_pattern.value,
|
{
|
||||||
&loc_can_pattern.value,
|
|
||||||
&loc_can_expr.value,
|
|
||||||
) {
|
|
||||||
is_closure = true;
|
|
||||||
|
|
||||||
// Since everywhere in the code it'll be referred to by its defined name,
|
// Since everywhere in the code it'll be referred to by its defined name,
|
||||||
// remove its generated name from the closure map. (We'll re-insert it later.)
|
// remove its generated name from the closure map. (We'll re-insert it later.)
|
||||||
let references = env.closures.remove(symbol).unwrap_or_else(|| {
|
let references = env.closures.remove(symbol).unwrap_or_else(|| {
|
||||||
|
@ -1113,52 +1128,74 @@ fn canonicalize_pending_def<'a>(
|
||||||
loc_body: body.clone(),
|
loc_body: body.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO exploit this fact to remove clones below
|
// Functions' references don't count in defs.
|
||||||
debug_assert_eq!(
|
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
||||||
vec![*defined_symbol],
|
// parent commit for the bug this fixed!
|
||||||
scope.idents().map(|t| t.1 .0).filter(|x| vars_by_symbol.contains_key(x)).collect::<Vec<_>>()
|
let refs = References::new();
|
||||||
|
|
||||||
|
refs_by_symbol.insert(*defined_symbol, (loc_can_pattern.region, refs));
|
||||||
|
|
||||||
|
let symbol = *defined_symbol;
|
||||||
|
let def = single_typed_can_def(
|
||||||
|
loc_can_pattern,
|
||||||
|
loc_can_expr,
|
||||||
|
expr_var,
|
||||||
|
Loc::at(loc_ann.region, ann),
|
||||||
|
vars_by_symbol.clone(),
|
||||||
);
|
);
|
||||||
}
|
can_defs_by_symbol.insert(symbol, def);
|
||||||
|
} else {
|
||||||
|
// Store the referenced locals in the refs_by_symbol map, so we can later figure out
|
||||||
|
// which defined names reference each other.
|
||||||
|
|
||||||
// Store the referenced locals in the refs_by_symbol map, so we can later figure out
|
if let Loc {
|
||||||
// which defined names reference each other.
|
region,
|
||||||
for (_, (symbol, region)) in scope.idents() {
|
value: Pattern::Identifier(symbol),
|
||||||
if !vars_by_symbol.contains_key(symbol) {
|
} = loc_can_pattern
|
||||||
continue;
|
{
|
||||||
}
|
let refs = can_output.references;
|
||||||
|
refs_by_symbol.insert(symbol, (region, refs));
|
||||||
|
|
||||||
let refs =
|
let def = single_typed_can_def(
|
||||||
// Functions' references don't count in defs.
|
loc_can_pattern,
|
||||||
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
loc_can_expr,
|
||||||
// parent commit for the bug this fixed!
|
|
||||||
if is_closure {
|
|
||||||
References::new()
|
|
||||||
} else {
|
|
||||||
can_output.references.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
refs_by_symbol.insert(*symbol, (*region, refs));
|
|
||||||
|
|
||||||
can_defs_by_symbol.insert(
|
|
||||||
*symbol,
|
|
||||||
Def {
|
|
||||||
expr_var,
|
expr_var,
|
||||||
// TODO try to remove this .clone()!
|
Loc::at(loc_ann.region, ann),
|
||||||
loc_pattern: loc_can_pattern.clone(),
|
vars_by_symbol.clone(),
|
||||||
loc_expr: Loc {
|
);
|
||||||
region: loc_can_expr.region,
|
can_defs_by_symbol.insert(symbol, def);
|
||||||
// TODO try to remove this .clone()!
|
} else {
|
||||||
value: loc_can_expr.value.clone(),
|
for (_, (symbol, region)) in scope.idents() {
|
||||||
},
|
if !vars_by_symbol.contains_key(symbol) {
|
||||||
pattern_vars: vars_by_symbol.clone(),
|
continue;
|
||||||
annotation: Some(Annotation {
|
}
|
||||||
signature: typ.clone(),
|
|
||||||
introduced_variables: ann.introduced_variables.clone(),
|
let refs = can_output.references.clone();
|
||||||
aliases: ann.aliases.clone(),
|
|
||||||
region: loc_ann.region,
|
refs_by_symbol.insert(*symbol, (*region, refs));
|
||||||
}),
|
|
||||||
},
|
can_defs_by_symbol.insert(
|
||||||
);
|
*symbol,
|
||||||
|
Def {
|
||||||
|
expr_var,
|
||||||
|
// TODO try to remove this .clone()!
|
||||||
|
loc_pattern: loc_can_pattern.clone(),
|
||||||
|
loc_expr: Loc {
|
||||||
|
region: loc_can_expr.region,
|
||||||
|
// TODO try to remove this .clone()!
|
||||||
|
value: loc_can_expr.value.clone(),
|
||||||
|
},
|
||||||
|
pattern_vars: vars_by_symbol.clone(),
|
||||||
|
annotation: Some(Annotation {
|
||||||
|
signature: ann.typ.clone(),
|
||||||
|
introduced_variables: ann.introduced_variables.clone(),
|
||||||
|
aliases: ann.aliases.clone(),
|
||||||
|
region: loc_ann.region,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we have a pattern, then the def has a body (that is, it's not a
|
// If we have a pattern, then the def has a body (that is, it's not a
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue