Skip to content

Commit 96c12f9

Browse files
committed
fixup! Implement the precise analysis pass for lint disjoint_capture_drop_reorder
1 parent 5b54640 commit 96c12f9

File tree

1 file changed

+34
-58
lines changed

1 file changed

+34
-58
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+34-58
Original file line numberDiff line numberDiff line change
@@ -540,21 +540,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
540540
span: Span,
541541
body: &'tcx hir::Body<'tcx>,
542542
) {
543-
let need_migrations_first_pass = self.compute_2229_migrations_first_pass(
543+
let need_migrations = self.compute_2229_migrations(
544544
closure_def_id,
545545
span,
546546
capture_clause,
547547
body,
548548
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
549549
);
550550

551-
let need_migrations = self.compute_2229_migrations_precise_pass(
552-
closure_def_id,
553-
span,
554-
self.typeck_results.borrow().closure_min_captures.get(&closure_def_id),
555-
&need_migrations_first_pass,
556-
);
557-
558551
if !need_migrations.is_empty() {
559552
let migrations_text = migration_suggestion_for_2229(self.tcx, &need_migrations);
560553

@@ -583,15 +576,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
583576
/// - It would have been moved into the closure when `capture_disjoint_fields` wasn't
584577
/// enabled, **and**
585578
/// - It wasn't completely captured by the closure, **and**
586-
/// - The type of the root variable needs Drop.
587-
fn compute_2229_migrations_first_pass(
579+
/// - One of the paths starting at this root variable, that is not captured needs Drop.
580+
fn compute_2229_migrations(
588581
&self,
589582
closure_def_id: DefId,
590583
closure_span: Span,
591584
closure_clause: hir::CaptureBy,
592585
body: &'tcx hir::Body<'tcx>,
593586
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
594-
) -> Vec<(hir::HirId, Ty<'tcx>)> {
587+
) -> Vec<hir::HirId> {
595588
fn resolve_ty<T: TypeFoldable<'tcx>>(
596589
fcx: &FnCtxt<'_, 'tcx>,
597590
span: Span,
@@ -627,64 +620,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
627620

628621
match closure_clause {
629622
// Only migrate if closure is a move closure
630-
hir::CaptureBy::Value => need_migrations.push((var_hir_id, ty)),
623+
hir::CaptureBy::Value => need_migrations.push(var_hir_id),
631624

632625
hir::CaptureBy::Ref => {}
633626
}
634627

635628
continue;
636629
};
637630

638-
let is_moved = root_var_min_capture_list
631+
let projections_list = root_var_min_capture_list
639632
.iter()
640-
.any(|capture| matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue(_)));
641-
642-
let is_not_completely_captured =
643-
root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0);
644-
645-
if is_moved && is_not_completely_captured {
646-
need_migrations.push((var_hir_id, ty));
647-
}
648-
}
649-
650-
need_migrations
651-
}
652-
653-
fn compute_2229_migrations_precise_pass(
654-
&self,
655-
closure_def_id: DefId,
656-
closure_span: Span,
657-
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
658-
need_migrations: &[(hir::HirId, Ty<'tcx>)],
659-
) -> Vec<hir::HirId> {
660-
// Need migrations -- second pass
661-
let mut need_migrations_2 = Vec::new();
662-
663-
for (hir_id, ty) in need_migrations {
664-
let projections_list = min_captures
665-
.and_then(|m| m.get(hir_id))
666-
.into_iter()
667-
.flatten()
668633
.filter_map(|captured_place| match captured_place.info.capture_kind {
669634
// Only care about captures that are moved into the closure
670635
ty::UpvarCapture::ByValue(..) => {
671636
Some(captured_place.place.projections.as_slice())
672637
}
673638
ty::UpvarCapture::ByRef(..) => None,
674639
})
675-
.collect();
640+
.collect::<Vec<_>>();
676641

677-
if self.has_significant_drop_outside_of_captures(
678-
closure_def_id,
679-
closure_span,
680-
ty,
681-
projections_list,
682-
) {
683-
need_migrations_2.push(*hir_id);
642+
let is_moved = !projections_list.is_empty();
643+
644+
let is_not_completely_captured =
645+
root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0);
646+
647+
if is_moved
648+
&& is_not_completely_captured
649+
&& self.has_significant_drop_outside_of_captures(
650+
closure_def_id,
651+
closure_span,
652+
ty,
653+
projections_list,
654+
)
655+
{
656+
need_migrations.push(var_hir_id);
684657
}
685658
}
686659

687-
need_migrations_2
660+
need_migrations
688661
}
689662

690663
/// This is a helper function to `compute_2229_migrations_precise_pass`. Provided the type
@@ -822,21 +795,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
822795

823796
assert!(!is_completely_captured || (captured_projs.len() == 1));
824797

825-
if is_drop_defined_for_ty {
826-
// If drop is implemented for this type then we need it to be fully captured, or
827-
// it will require migration.
828-
return !is_completely_captured;
829-
}
830-
831798
if is_completely_captured {
832799
// The place is captured entirely, so doesn't matter if needs dtor, it will be drop
833800
// when the closure is dropped.
834801
return false;
835802
}
836803

837-
match base_path_ty.kind() {
838-
_ if captured_projs.is_empty() => needs_drop(base_path_ty),
804+
if is_drop_defined_for_ty {
805+
// If drop is implemented for this type then we need it to be fully captured,
806+
// which we know it is not because of the previous check. Therefore we need to
807+
// do migrate.
808+
return true;
809+
}
810+
811+
if captured_projs.is_empty() {
812+
return needs_drop(base_path_ty);
813+
}
839814

815+
match base_path_ty.kind() {
840816
// Observations:
841817
// - `captured_projs` is not empty. Therefore we can call
842818
// `captured_projs.first().unwrap()` safely.

0 commit comments

Comments
 (0)