Replace closures_captures and upvar_capture with closure_min_captures
make changes to liveness to use closure_min_captures use different span borrow check uses new structures rename to CapturedPlace stop using upvar_capture in regionck remove the bridge cleanup from rebase + remove the upvar_capture reference from mutability_errors.rs remove line from livenes test make our unused var checking more consistent update tests adding more warnings to the tests move is_ancestor_or_same_capture to rustc_middle/ty update names to reflect the closures add FIXME check that all captures are immutable borrows before returning add surrounding if statement like the original move var out of the loop and rename Co-authored-by: Logan Mosier <logmosier@gmail.com> Co-authored-by: Roxane Fruytier <roxane.fruytier@hotmail.com>
This commit is contained in:
parent
1705a7d64b
commit
52dba13e41
14 changed files with 477 additions and 243 deletions
|
@ -771,21 +771,39 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
|
|||
debug!("link_upvar_region(borrorw_region={:?}, upvar_id={:?}", borrow_region, upvar_id);
|
||||
// A by-reference upvar can't be borrowed for longer than the
|
||||
// upvar is borrowed from the environment.
|
||||
match self.typeck_results.borrow().upvar_capture(upvar_id) {
|
||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||
self.sub_regions(
|
||||
infer::ReborrowUpvar(span, upvar_id),
|
||||
borrow_region,
|
||||
upvar_borrow.region,
|
||||
);
|
||||
if let ty::ImmBorrow = upvar_borrow.kind {
|
||||
debug!("link_upvar_region: capture by shared ref");
|
||||
return;
|
||||
let closure_local_def_id = upvar_id.closure_expr_id;
|
||||
let mut all_captures_are_imm_borrow = true;
|
||||
for captured_place in self
|
||||
.typeck_results
|
||||
.borrow()
|
||||
.closure_min_captures
|
||||
.get(&closure_local_def_id.to_def_id())
|
||||
.and_then(|root_var_min_cap| root_var_min_cap.get(&upvar_id.var_path.hir_id))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
match captured_place.info.capture_kind {
|
||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||
self.sub_regions(
|
||||
infer::ReborrowUpvar(span, upvar_id),
|
||||
borrow_region,
|
||||
upvar_borrow.region,
|
||||
);
|
||||
if let ty::ImmBorrow = upvar_borrow.kind {
|
||||
debug!("link_upvar_region: capture by shared ref");
|
||||
} else {
|
||||
all_captures_are_imm_borrow = false;
|
||||
}
|
||||
}
|
||||
ty::UpvarCapture::ByValue(_) => {
|
||||
all_captures_are_imm_borrow = false;
|
||||
}
|
||||
}
|
||||
ty::UpvarCapture::ByValue(_) => {}
|
||||
}
|
||||
let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id);
|
||||
if all_captures_are_imm_borrow {
|
||||
return;
|
||||
}
|
||||
let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
|
||||
let ty = self.resolve_node_type(fn_hir_id);
|
||||
debug!("link_upvar_region: ty={:?}", ty);
|
||||
|
||||
|
|
|
@ -222,8 +222,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.log_closure_min_capture_info(closure_def_id, span);
|
||||
|
||||
self.min_captures_to_closure_captures_bridge(closure_def_id);
|
||||
|
||||
// Now that we've analyzed the closure, we know how each
|
||||
// variable is borrowed, and we know what traits the closure
|
||||
// implements (Fn vs FnMut etc). We now have some updates to do
|
||||
|
@ -293,80 +291,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Bridge for closure analysis
|
||||
/// ----------------------------
|
||||
///
|
||||
/// For closure with DefId `c`, the bridge converts structures required for supporting RFC 2229,
|
||||
/// to structures currently used in the compiler for handling closure captures.
|
||||
///
|
||||
/// For example the following structure will be converted:
|
||||
///
|
||||
/// closure_min_captures
|
||||
/// foo -> [ {foo.x, ImmBorrow}, {foo.y, MutBorrow} ]
|
||||
/// bar -> [ {bar.z, ByValue}, {bar.q, MutBorrow} ]
|
||||
///
|
||||
/// to
|
||||
///
|
||||
/// 1. closure_captures
|
||||
/// foo -> UpvarId(foo, c), bar -> UpvarId(bar, c)
|
||||
///
|
||||
/// 2. upvar_capture_map
|
||||
/// UpvarId(foo,c) -> MutBorrow, UpvarId(bar, c) -> ByValue
|
||||
fn min_captures_to_closure_captures_bridge(&self, closure_def_id: DefId) {
|
||||
let mut closure_captures: FxIndexMap<hir::HirId, ty::UpvarId> = Default::default();
|
||||
let mut upvar_capture_map = ty::UpvarCaptureMap::default();
|
||||
|
||||
if let Some(min_captures) =
|
||||
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id)
|
||||
{
|
||||
for (var_hir_id, min_list) in min_captures.iter() {
|
||||
for captured_place in min_list {
|
||||
let place = &captured_place.place;
|
||||
let capture_info = captured_place.info;
|
||||
|
||||
let upvar_id = match place.base {
|
||||
PlaceBase::Upvar(upvar_id) => upvar_id,
|
||||
base => bug!("Expected upvar, found={:?}", base),
|
||||
};
|
||||
|
||||
assert_eq!(upvar_id.var_path.hir_id, *var_hir_id);
|
||||
assert_eq!(upvar_id.closure_expr_id, closure_def_id.expect_local());
|
||||
|
||||
closure_captures.insert(*var_hir_id, upvar_id);
|
||||
|
||||
let new_capture_kind =
|
||||
if let Some(capture_kind) = upvar_capture_map.get(&upvar_id) {
|
||||
// upvar_capture_map only stores the UpvarCapture (CaptureKind),
|
||||
// so we create a fake capture info with no expression.
|
||||
let fake_capture_info = ty::CaptureInfo {
|
||||
capture_kind_expr_id: None,
|
||||
path_expr_id: None,
|
||||
capture_kind: *capture_kind,
|
||||
};
|
||||
determine_capture_info(fake_capture_info, capture_info).capture_kind
|
||||
} else {
|
||||
capture_info.capture_kind
|
||||
};
|
||||
upvar_capture_map.insert(upvar_id, new_capture_kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("For closure_def_id={:?}, closure_captures={:#?}", closure_def_id, closure_captures);
|
||||
debug!(
|
||||
"For closure_def_id={:?}, upvar_capture_map={:#?}",
|
||||
closure_def_id, upvar_capture_map
|
||||
);
|
||||
|
||||
if !closure_captures.is_empty() {
|
||||
self.typeck_results
|
||||
.borrow_mut()
|
||||
.closure_captures
|
||||
.insert(closure_def_id, closure_captures);
|
||||
|
||||
self.typeck_results.borrow_mut().upvar_capture_map.extend(upvar_capture_map);
|
||||
}
|
||||
}
|
||||
|
||||
/// Analyzes the information collected by `InferBorrowKind` to compute the min number of
|
||||
/// Places (and corresponding capture kind) that we need to keep track of to support all
|
||||
/// the required captured paths.
|
||||
|
|
|
@ -61,7 +61,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
wbcx.visit_body(body);
|
||||
wbcx.visit_min_capture_map();
|
||||
wbcx.visit_fake_reads_map();
|
||||
wbcx.visit_upvar_capture_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_liberated_fn_sigs();
|
||||
wbcx.visit_fru_field_types();
|
||||
|
@ -79,9 +78,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
wbcx.typeck_results.treat_byte_string_as_slice =
|
||||
mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
|
||||
|
||||
wbcx.typeck_results.closure_captures =
|
||||
mem::take(&mut self.typeck_results.borrow_mut().closure_captures);
|
||||
|
||||
if self.is_tainted_by_errors() {
|
||||
// FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
|
||||
wbcx.typeck_results.tainted_by_errors = Some(ErrorReported);
|
||||
|
@ -389,22 +385,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
self.typeck_results.closure_fake_reads = resolved_closure_fake_reads;
|
||||
}
|
||||
|
||||
fn visit_upvar_capture_map(&mut self) {
|
||||
for (upvar_id, upvar_capture) in self.fcx.typeck_results.borrow().upvar_capture_map.iter() {
|
||||
let new_upvar_capture = match *upvar_capture {
|
||||
ty::UpvarCapture::ByValue(span) => ty::UpvarCapture::ByValue(span),
|
||||
ty::UpvarCapture::ByRef(ref upvar_borrow) => {
|
||||
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
|
||||
kind: upvar_borrow.kind,
|
||||
region: self.tcx().lifetimes.re_erased,
|
||||
})
|
||||
}
|
||||
};
|
||||
debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture);
|
||||
self.typeck_results.upvar_capture_map.insert(*upvar_id, new_upvar_capture);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_closures(&mut self) {
|
||||
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue