in starlark/src/eval/compiler/scope.rs [546:602]
fn collect_assign_ident<'a>(
assign: &'a mut CstAssignIdent,
in_loop: InLoop,
vis: Visibility,
scope_data: &mut ScopeData,
result: &mut IndexMap<&'a str, BindingId>,
) {
// Helper function to untangle lifetimes: we read and modify `assign` fields.
fn assign_ident_impl<'b>(
name: &'b str,
binding: &'b mut Option<BindingId>,
in_loop: InLoop,
mut vis: Visibility,
scope_data: &mut ScopeData,
result: &mut IndexMap<&'b str, BindingId>,
) {
assert!(
binding.is_none(),
"binding can be assigned only once: `{}`",
name
);
if vis == Visibility::Public {
vis = Module::default_visibility(name);
}
match result.entry(name) {
indexmap::map::Entry::Occupied(e) => {
let prev_binding_id = *e.get();
let prev_binding = scope_data.mut_binding(prev_binding_id);
// If we are in the map as Public and Private, then Public wins.
// Everything but Load is definitely Public.
// So only insert if it wasn't already there.
if vis == Visibility::Public {
prev_binding.vis = Visibility::Public;
}
prev_binding.assign_count = AssignCount::Any;
*binding = Some(prev_binding_id);
}
indexmap::map::Entry::Vacant(e) => {
let assign_count = match in_loop {
InLoop::Yes => AssignCount::Any,
InLoop::No => AssignCount::AtMostOnce,
};
let (new_binding_id, _) = scope_data.new_binding(vis, assign_count);
e.insert(new_binding_id);
*binding = Some(new_binding_id);
}
};
}
assign_ident_impl(
&assign.node.0,
&mut assign.node.1,
in_loop,
vis,
scope_data,
result,
);
}