fixup! Implement the precise analysis pass for lint disjoint_capture_drop_reorder
This commit is contained in:
parent
5b54640128
commit
96c12f90cf
1 changed files with 34 additions and 58 deletions
|
@ -540,7 +540,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
body: &'tcx hir::Body<'tcx>,
|
body: &'tcx hir::Body<'tcx>,
|
||||||
) {
|
) {
|
||||||
let need_migrations_first_pass = self.compute_2229_migrations_first_pass(
|
let need_migrations = self.compute_2229_migrations(
|
||||||
closure_def_id,
|
closure_def_id,
|
||||||
span,
|
span,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
@ -548,13 +548,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
|
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
|
||||||
);
|
);
|
||||||
|
|
||||||
let need_migrations = self.compute_2229_migrations_precise_pass(
|
|
||||||
closure_def_id,
|
|
||||||
span,
|
|
||||||
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
|
|
||||||
&need_migrations_first_pass,
|
|
||||||
);
|
|
||||||
|
|
||||||
if !need_migrations.is_empty() {
|
if !need_migrations.is_empty() {
|
||||||
let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations);
|
let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations);
|
||||||
|
|
||||||
|
@ -583,15 +576,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// - It would have been moved into the closure when `capture_disjoint_fields` wasn't
|
/// - It would have been moved into the closure when `capture_disjoint_fields` wasn't
|
||||||
/// enabled, **and**
|
/// enabled, **and**
|
||||||
/// - It wasn't completely captured by the closure, **and**
|
/// - It wasn't completely captured by the closure, **and**
|
||||||
/// - The type of the root variable needs Drop.
|
/// - One of the paths starting at this root variable, that is not captured needs Drop.
|
||||||
fn compute_2229_migrations_first_pass(
|
fn compute_2229_migrations(
|
||||||
&self,
|
&self,
|
||||||
closure_def_id: DefId,
|
closure_def_id: DefId,
|
||||||
closure_span: Span,
|
closure_span: Span,
|
||||||
closure_clause: hir::CaptureBy,
|
closure_clause: hir::CaptureBy,
|
||||||
body: &'tcx hir::Body<'tcx>,
|
body: &'tcx hir::Body<'tcx>,
|
||||||
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
|
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
|
||||||
) -> Vec<(hir::HirId, Ty<'tcx>)> {
|
) -> Vec<hir::HirId> {
|
||||||
fn resolve_ty<T: TypeFoldable<'tcx>>(
|
fn resolve_ty<T: TypeFoldable<'tcx>>(
|
||||||
fcx: &FnCtxt<'_, 'tcx>,
|
fcx: &FnCtxt<'_, 'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -627,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
match closure_clause {
|
match closure_clause {
|
||||||
// Only migrate if closure is a move closure
|
// Only migrate if closure is a move closure
|
||||||
hir::CaptureBy::Value => need_migrations.push((var_hir_id, ty)),
|
hir::CaptureBy::Value => need_migrations.push(var_hir_id),
|
||||||
|
|
||||||
hir::CaptureBy::Ref => {}
|
hir::CaptureBy::Ref => {}
|
||||||
}
|
}
|
||||||
|
@ -635,36 +628,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_moved = root_var_min_capture_list
|
let projections_list = root_var_min_capture_list
|
||||||
.iter()
|
.iter()
|
||||||
.any(|capture| matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue(_)));
|
|
||||||
|
|
||||||
let is_not_completely_captured =
|
|
||||||
root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0);
|
|
||||||
|
|
||||||
if is_moved && is_not_completely_captured {
|
|
||||||
need_migrations.push((var_hir_id, ty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
need_migrations
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_2229_migrations_precise_pass(
|
|
||||||
&self,
|
|
||||||
closure_def_id: DefId,
|
|
||||||
closure_span: Span,
|
|
||||||
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
|
|
||||||
need_migrations: &[(hir::HirId, Ty<'tcx>)],
|
|
||||||
) -> Vec<hir::HirId> {
|
|
||||||
// Need migrations -- second pass
|
|
||||||
let mut need_migrations_2 = Vec::new();
|
|
||||||
|
|
||||||
for (hir_id, ty) in need_migrations {
|
|
||||||
let projections_list = min_captures
|
|
||||||
.and_then(|m| m.get(hir_id))
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.filter_map(|captured_place| match captured_place.info.capture_kind {
|
.filter_map(|captured_place| match captured_place.info.capture_kind {
|
||||||
// Only care about captures that are moved into the closure
|
// Only care about captures that are moved into the closure
|
||||||
ty::UpvarCapture::ByValue(..) => {
|
ty::UpvarCapture::ByValue(..) => {
|
||||||
|
@ -672,19 +637,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::UpvarCapture::ByRef(..) => None,
|
ty::UpvarCapture::ByRef(..) => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if self.has_significant_drop_outside_of_captures(
|
let is_moved = !projections_list.is_empty();
|
||||||
closure_def_id,
|
|
||||||
closure_span,
|
let is_not_completely_captured =
|
||||||
ty,
|
root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0);
|
||||||
projections_list,
|
|
||||||
) {
|
if is_moved
|
||||||
need_migrations_2.push(*hir_id);
|
&& is_not_completely_captured
|
||||||
|
&& self.has_significant_drop_outside_of_captures(
|
||||||
|
closure_def_id,
|
||||||
|
closure_span,
|
||||||
|
ty,
|
||||||
|
projections_list,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
need_migrations.push(var_hir_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
need_migrations_2
|
need_migrations
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a helper function to `compute_2229_migrations_precise_pass`. Provided the type
|
/// This is a helper function to `compute_2229_migrations_precise_pass`. Provided the type
|
||||||
|
@ -822,21 +795,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
assert!(!is_completely_captured || (captured_projs.len() == 1));
|
assert!(!is_completely_captured || (captured_projs.len() == 1));
|
||||||
|
|
||||||
if is_drop_defined_for_ty {
|
|
||||||
// If drop is implemented for this type then we need it to be fully captured, or
|
|
||||||
// it will require migration.
|
|
||||||
return !is_completely_captured;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_completely_captured {
|
if is_completely_captured {
|
||||||
// The place is captured entirely, so doesn't matter if needs dtor, it will be drop
|
// The place is captured entirely, so doesn't matter if needs dtor, it will be drop
|
||||||
// when the closure is dropped.
|
// when the closure is dropped.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
match base_path_ty.kind() {
|
if is_drop_defined_for_ty {
|
||||||
_ if captured_projs.is_empty() => needs_drop(base_path_ty),
|
// If drop is implemented for this type then we need it to be fully captured,
|
||||||
|
// which we know it is not because of the previous check. Therefore we need to
|
||||||
|
// do migrate.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if captured_projs.is_empty() {
|
||||||
|
return needs_drop(base_path_ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
match base_path_ty.kind() {
|
||||||
// Observations:
|
// Observations:
|
||||||
// - `captured_projs` is not empty. Therefore we can call
|
// - `captured_projs` is not empty. Therefore we can call
|
||||||
// `captured_projs.first().unwrap()` safely.
|
// `captured_projs.first().unwrap()` safely.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue