@@ -639,7 +639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639
639
/// `w[c]`.
640
640
/// Notation:
641
641
/// - Ty(place): Type of place
642
- /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_projs `
642
+ /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs `
643
643
/// respectively.
644
644
/// ```
645
645
/// (Ty(w), [ &[p, x], &[c] ])
@@ -700,7 +700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
700
700
closure_def_id : DefId ,
701
701
closure_span : Span ,
702
702
base_path_ty : Ty < ' tcx > ,
703
- captured_projs : Vec < & [ Projection < ' tcx > ] > ,
703
+ captured_by_move_projs : Vec < & [ Projection < ' tcx > ] > ,
704
704
) -> bool {
705
705
let needs_drop = |ty : Ty < ' tcx > | {
706
706
ty. needs_drop ( self . tcx , self . tcx . param_env ( closure_def_id. expect_local ( ) ) )
@@ -725,33 +725,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
725
725
//
726
726
// eg. If `a.b` is captured and we are processing `a.b`, then we can't have the closure also
727
727
// capture `a.b.c`, because that voilates min capture.
728
- let is_completely_captured = captured_projs . iter ( ) . any ( |projs| projs. is_empty ( ) ) ;
728
+ let is_completely_captured = captured_by_move_projs . iter ( ) . any ( |projs| projs. is_empty ( ) ) ;
729
729
730
- assert ! ( !is_completely_captured || ( captured_projs . len( ) == 1 ) ) ;
730
+ assert ! ( !is_completely_captured || ( captured_by_move_projs . len( ) == 1 ) ) ;
731
731
732
732
if is_completely_captured {
733
733
// The place is captured entirely, so doesn't matter if needs dtor, it will be drop
734
734
// when the closure is dropped.
735
735
return false ;
736
736
}
737
737
738
+ if captured_by_move_projs. is_empty ( ) {
739
+ return needs_drop ( base_path_ty) ;
740
+ }
741
+
738
742
if is_drop_defined_for_ty {
739
743
// If drop is implemented for this type then we need it to be fully captured,
740
- // which we know it is not because of the previous check. Therefore we need to
741
- // do migrate.
742
- return true ;
743
- }
744
+ // and we know it is not completely captured because of the previous checks.
744
745
745
- if captured_projs. is_empty ( ) {
746
- return needs_drop ( base_path_ty) ;
746
+ // Note that this is a bug in the user code that will be reported by the
747
+ // borrow checker, since we can't move out of drop types.
748
+
749
+ // The bug exists in the user's code pre-migration, and we don't migrate here.
750
+ return false ;
747
751
}
748
752
749
753
match base_path_ty. kind ( ) {
750
754
// Observations:
751
- // - `captured_projs ` is not empty. Therefore we can call
752
- // `captured_projs .first().unwrap()` safely.
753
- // - All entries in `captured_projs ` have atleast one projection.
754
- // Therefore we can call `captured_projs .first().unwrap().first().unwrap()` safely.
755
+ // - `captured_by_move_projs ` is not empty. Therefore we can call
756
+ // `captured_by_move_projs .first().unwrap()` safely.
757
+ // - All entries in `captured_by_move_projs ` have atleast one projection.
758
+ // Therefore we can call `captured_by_move_projs .first().unwrap().first().unwrap()` safely.
755
759
756
760
// We don't capture derefs in case of move captures, which would have be applied to
757
761
// access any further paths.
@@ -761,19 +765,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
761
765
762
766
ty:: Adt ( def, substs) => {
763
767
// Multi-varaint enums are captured in entirety,
764
- // which would've been handled in the case of single empty slice in `captured_projs `.
768
+ // which would've been handled in the case of single empty slice in `captured_by_move_projs `.
765
769
assert_eq ! ( def. variants. len( ) , 1 ) ;
766
770
767
771
// Only Field projections can be applied to a non-box Adt.
768
772
assert ! (
769
- captured_projs . iter( ) . all( |projs| matches!(
773
+ captured_by_move_projs . iter( ) . all( |projs| matches!(
770
774
projs. first( ) . unwrap( ) . kind,
771
775
ProjectionKind :: Field ( ..)
772
776
) )
773
777
) ;
774
778
def. variants . get ( VariantIdx :: new ( 0 ) ) . unwrap ( ) . fields . iter ( ) . enumerate ( ) . any (
775
779
|( i, field) | {
776
- let paths_using_field = captured_projs
780
+ let paths_using_field = captured_by_move_projs
777
781
. iter ( )
778
782
. filter_map ( |projs| {
779
783
if let ProjectionKind :: Field ( field_idx, _) =
@@ -800,14 +804,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
800
804
ty:: Tuple ( ..) => {
801
805
// Only Field projections can be applied to a tuple.
802
806
assert ! (
803
- captured_projs . iter( ) . all( |projs| matches!(
807
+ captured_by_move_projs . iter( ) . all( |projs| matches!(
804
808
projs. first( ) . unwrap( ) . kind,
805
809
ProjectionKind :: Field ( ..)
806
810
) )
807
811
) ;
808
812
809
813
base_path_ty. tuple_fields ( ) . enumerate ( ) . any ( |( i, element_ty) | {
810
- let paths_using_field = captured_projs
814
+ let paths_using_field = captured_by_move_projs
811
815
. iter ( )
812
816
. filter_map ( |projs| {
813
817
if let ProjectionKind :: Field ( field_idx, _) = projs. first ( ) . unwrap ( ) . kind
0 commit comments