K: Clone + Eq + Hash,
V: Eq + Hash,
{
- map.entry(k.clone()).or_insert(FxHashSet()).insert(v);
+ map.entry(k.clone()).or_default().insert(v);
}
}
// ... check whether we (earlier) saw a 2-phase borrow like
//
// TMP = &mut place
- match self.pending_activations.get(temp) {
- Some(&borrow_index) => {
- let borrow_data = &mut self.idx_vec[borrow_index];
-
- // Watch out: the use of TMP in the borrow itself
- // doesn't count as an activation. =)
- if borrow_data.reserve_location == location && context == PlaceContext::Store {
- return;
- }
+ if let Some(&borrow_index) = self.pending_activations.get(temp) {
+ let borrow_data = &mut self.idx_vec[borrow_index];
- if let TwoPhaseActivation::ActivatedAt(other_location) =
- borrow_data.activation_location {
- span_bug!(
- self.mir.source_info(location).span,
- "found two uses for 2-phase borrow temporary {:?}: \
- {:?} and {:?}",
- temp,
- location,
- other_location,
- );
- }
+ // Watch out: the use of TMP in the borrow itself
+ // doesn't count as an activation. =)
+ if borrow_data.reserve_location == location && context == PlaceContext::Store {
+ return;
+ }
- // Otherwise, this is the unique later use
- // that we expect.
- borrow_data.activation_location = match context {
- // The use of TMP in a shared borrow does not
- // count as an actual activation.
- PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. }
- | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => {
- TwoPhaseActivation::NotActivated
- }
- _ => {
- // Double check: This borrow is indeed a two-phase borrow (that is,
- // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and
- // we've not found any other activations (checked above).
- assert_eq!(
- borrow_data.activation_location,
- TwoPhaseActivation::NotActivated,
- "never found an activation for this borrow!",
- );
-
- self.activation_map
- .entry(location)
- .or_default()
- .push(borrow_index);
- TwoPhaseActivation::ActivatedAt(location)
- }
- };
+ if let TwoPhaseActivation::ActivatedAt(other_location) =
+ borrow_data.activation_location {
+ span_bug!(
+ self.mir.source_info(location).span,
+ "found two uses for 2-phase borrow temporary {:?}: \
+ {:?} and {:?}",
+ temp,
+ location,
+ other_location,
+ );
}
- None => {}
+ // Otherwise, this is the unique later use
+ // that we expect.
+ borrow_data.activation_location = match context {
+ // The use of TMP in a shared borrow does not
+ // count as an actual activation.
+ PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. }
+ | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => {
+ TwoPhaseActivation::NotActivated
+ }
+ _ => {
+ // Double check: This borrow is indeed a two-phase borrow (that is,
+ // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and
+ // we've not found any other activations (checked above).
+ assert_eq!(
+ borrow_data.activation_location,
+ TwoPhaseActivation::NotActivated,
+ "never found an activation for this borrow!",
+ );
+
+ self.activation_map
+ .entry(location)
+ .or_default()
+ .push(borrow_index);
+ TwoPhaseActivation::ActivatedAt(location)
+ }
+ };
}
}
}
let tables = self.infcx.tcx.typeck_tables_of(id);
let node_id = self.infcx.tcx.hir.as_local_node_id(id).unwrap();
let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id);
- if tables.closure_kind_origins().get(hir_id).is_some() {
- false
- } else {
- true
- }
+
+ tables.closure_kind_origins().get(hir_id).is_none()
}
_ => true,
};
"annotate_argument_and_return_for_borrow: location={:?}",
location
);
- match &self.mir[location.block]
- .statements
- .get(location.statement_index)
+ if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..})
+ = &self.mir[location.block].statements.get(location.statement_index)
{
- Some(&Statement {
- kind: StatementKind::Assign(ref reservation, _),
- ..
- }) => {
+ debug!(
+ "annotate_argument_and_return_for_borrow: reservation={:?}",
+ reservation
+ );
+ // Check that the initial assignment of the reserve location is into a temporary.
+ let mut target = *match reservation {
+ Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
+ _ => return None,
+ };
+
+ // Next, look through the rest of the block, checking if we are assigning the
+ // `target` (that is, the place that contains our borrow) to anything.
+ let mut annotated_closure = None;
+ for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
debug!(
- "annotate_argument_and_return_for_borrow: reservation={:?}",
- reservation
+ "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
+ target, stmt
);
- // Check that the initial assignment of the reserve location is into a temporary.
- let mut target = *match reservation {
- Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
- _ => return None,
- };
-
- // Next, look through the rest of the block, checking if we are assigning the
- // `target` (that is, the place that contains our borrow) to anything.
- let mut annotated_closure = None;
- for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
+ if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
+ {
debug!(
- "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
- target, stmt
+ "annotate_argument_and_return_for_borrow: assigned_to={:?} \
+ rvalue={:?}",
+ assigned_to, rvalue
);
- if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
+ // Check if our `target` was captured by a closure.
+ if let Rvalue::Aggregate(
+ box AggregateKind::Closure(def_id, substs),
+ operands,
+ ) = rvalue
{
- debug!(
- "annotate_argument_and_return_for_borrow: assigned_to={:?} \
- rvalue={:?}",
- assigned_to, rvalue
- );
- // Check if our `target` was captured by a closure.
- if let Rvalue::Aggregate(
- box AggregateKind::Closure(def_id, substs),
- operands,
- ) = rvalue
- {
- for operand in operands {
- let assigned_from = match operand {
- Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
- assigned_from
- }
- _ => continue,
- };
- debug!(
- "annotate_argument_and_return_for_borrow: assigned_from={:?}",
+ for operand in operands {
+ let assigned_from = match operand {
+ Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
assigned_from
- );
-
- // Find the local from the operand.
- let assigned_from_local = match assigned_from.local() {
- Some(local) => local,
- None => continue,
- };
-
- if assigned_from_local != target {
- continue;
}
+ _ => continue,
+ };
+ debug!(
+ "annotate_argument_and_return_for_borrow: assigned_from={:?}",
+ assigned_from
+ );
- // If a closure captured our `target` and then assigned
- // into a place then we should annotate the closure in
- // case it ends up being assigned into the return place.
- annotated_closure = self.annotate_fn_sig(
- *def_id,
- self.infcx.closure_sig(*def_id, *substs),
- );
- debug!(
- "annotate_argument_and_return_for_borrow: \
- annotated_closure={:?} assigned_from_local={:?} \
- assigned_to={:?}",
- annotated_closure, assigned_from_local, assigned_to
- );
-
- if *assigned_to == mir::RETURN_PLACE {
- // If it was assigned directly into the return place, then
- // return now.
- return annotated_closure;
- } else {
- // Otherwise, update the target.
- target = *assigned_to;
- }
+ // Find the local from the operand.
+ let assigned_from_local = match assigned_from.local() {
+ Some(local) => local,
+ None => continue,
+ };
+
+ if assigned_from_local != target {
+ continue;
}
- // If none of our closure's operands matched, then skip to the next
- // statement.
- continue;
+ // If a closure captured our `target` and then assigned
+ // into a place then we should annotate the closure in
+ // case it ends up being assigned into the return place.
+ annotated_closure = self.annotate_fn_sig(
+ *def_id,
+ self.infcx.closure_sig(*def_id, *substs),
+ );
+ debug!(
+ "annotate_argument_and_return_for_borrow: \
+ annotated_closure={:?} assigned_from_local={:?} \
+ assigned_to={:?}",
+ annotated_closure, assigned_from_local, assigned_to
+ );
+
+ if *assigned_to == mir::RETURN_PLACE {
+ // If it was assigned directly into the return place, then
+ // return now.
+ return annotated_closure;
+ } else {
+ // Otherwise, update the target.
+ target = *assigned_to;
+ }
}
- // Otherwise, look at other types of assignment.
- let assigned_from = match rvalue {
- Rvalue::Ref(_, _, assigned_from) => assigned_from,
- Rvalue::Use(operand) => match operand {
- Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
- assigned_from
- }
- _ => continue,
- },
- _ => continue,
- };
- debug!(
- "annotate_argument_and_return_for_borrow: \
- assigned_from={:?}",
- assigned_from,
- );
+ // If none of our closure's operands matched, then skip to the next
+ // statement.
+ continue;
+ }
- // Find the local from the rvalue.
- let assigned_from_local = match assigned_from.local() {
- Some(local) => local,
- None => continue,
- };
- debug!(
- "annotate_argument_and_return_for_borrow: \
- assigned_from_local={:?}",
- assigned_from_local,
- );
+ // Otherwise, look at other types of assignment.
+ let assigned_from = match rvalue {
+ Rvalue::Ref(_, _, assigned_from) => assigned_from,
+ Rvalue::Use(operand) => match operand {
+ Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+ assigned_from
+ }
+ _ => continue,
+ },
+ _ => continue,
+ };
+ debug!(
+ "annotate_argument_and_return_for_borrow: \
+ assigned_from={:?}",
+ assigned_from,
+ );
- // Check if our local matches the target - if so, we've assigned our
- // borrow to a new place.
- if assigned_from_local != target {
- continue;
- }
+ // Find the local from the rvalue.
+ let assigned_from_local = match assigned_from.local() {
+ Some(local) => local,
+ None => continue,
+ };
+ debug!(
+ "annotate_argument_and_return_for_borrow: \
+ assigned_from_local={:?}",
+ assigned_from_local,
+ );
- // If we assigned our `target` into a new place, then we should
- // check if it was the return place.
- debug!(
- "annotate_argument_and_return_for_borrow: \
- assigned_from_local={:?} assigned_to={:?}",
- assigned_from_local, assigned_to
- );
- if *assigned_to == mir::RETURN_PLACE {
- // If it was then return the annotated closure if there was one,
- // else, annotate this function.
- return annotated_closure.or_else(fallback);
- }
+ // Check if our local matches the target - if so, we've assigned our
+ // borrow to a new place.
+ if assigned_from_local != target {
+ continue;
+ }
- // If we didn't assign into the return place, then we just update
- // the target.
- target = *assigned_to;
+ // If we assigned our `target` into a new place, then we should
+ // check if it was the return place.
+ debug!(
+ "annotate_argument_and_return_for_borrow: \
+ assigned_from_local={:?} assigned_to={:?}",
+ assigned_from_local, assigned_to
+ );
+ if *assigned_to == mir::RETURN_PLACE {
+ // If it was then return the annotated closure if there was one,
+ // else, annotate this function.
+ return annotated_closure.or_else(fallback);
}
+
+ // If we didn't assign into the return place, then we just update
+ // the target.
+ target = *assigned_to;
}
+ }
- // Check the terminator if we didn't find anything in the statements.
- let terminator = &self.mir[location.block].terminator();
+ // Check the terminator if we didn't find anything in the statements.
+ let terminator = &self.mir[location.block].terminator();
+ debug!(
+ "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
+ target, terminator
+ );
+ if let TerminatorKind::Call {
+ destination: Some((Place::Local(assigned_to), _)),
+ args,
+ ..
+ } = &terminator.kind
+ {
debug!(
- "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
- target, terminator
+ "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
+ assigned_to, args
);
- if let TerminatorKind::Call {
- destination: Some((Place::Local(assigned_to), _)),
- args,
- ..
- } = &terminator.kind
- {
+ for operand in args {
+ let assigned_from = match operand {
+ Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+ assigned_from
+ }
+ _ => continue,
+ };
debug!(
- "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
- assigned_to, args
+ "annotate_argument_and_return_for_borrow: assigned_from={:?}",
+ assigned_from,
);
- for operand in args {
- let assigned_from = match operand {
- Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
- assigned_from
- }
- _ => continue,
- };
+
+ if let Some(assigned_from_local) = assigned_from.local() {
debug!(
- "annotate_argument_and_return_for_borrow: assigned_from={:?}",
- assigned_from,
+ "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
+ assigned_from_local,
);
- if let Some(assigned_from_local) = assigned_from.local() {
- debug!(
- "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
- assigned_from_local,
- );
-
- if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
- return annotated_closure.or_else(fallback);
- }
+ if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
+ return annotated_closure.or_else(fallback);
}
}
}
}
- _ => {}
}
// If we haven't found an assignment into the return place, then we need not add
// Need to use the `rustc::ty` types to compare against the
// `return_region`. Then use the `rustc::hir` type to get only
// the lifetime span.
- match &fn_decl.inputs[index].node {
- hir::TyKind::Rptr(lifetime, _) => {
- // With access to the lifetime, we can get
- // the span of it.
- arguments.push((*argument, lifetime.span));
- }
- _ => bug!("ty type is a ref but hir type is not"),
+ if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].node {
+ // With access to the lifetime, we can get
+ // the span of it.
+ arguments.push((*argument, lifetime.span));
+ } else {
+ bug!("ty type is a ref but hir type is not");
}
}
}