@@ -639,7 +639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639639 /// `w[c]`.
640640 /// Notation:
641641 /// - 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 `
643643 /// respectively.
644644 /// ```
645645 /// (Ty(w), [ &[p, x], &[c] ])
@@ -700,7 +700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
700700 closure_def_id : DefId ,
701701 closure_span : Span ,
702702 base_path_ty : Ty < ' tcx > ,
703- captured_projs : Vec < & [ Projection < ' tcx > ] > ,
703+ captured_by_move_projs : Vec < & [ Projection < ' tcx > ] > ,
704704 ) -> bool {
705705 let needs_drop = |ty : Ty < ' tcx > | {
706706 ty. needs_drop ( self . tcx , self . tcx . param_env ( closure_def_id. expect_local ( ) ) )
@@ -725,33 +725,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
725725 //
726726 // eg. If `a.b` is captured and we are processing `a.b`, then we can't have the closure also
727727 // 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 ( ) ) ;
729729
730- assert ! ( !is_completely_captured || ( captured_projs . len( ) == 1 ) ) ;
730+ assert ! ( !is_completely_captured || ( captured_by_move_projs . len( ) == 1 ) ) ;
731731
732732 if is_completely_captured {
733733 // The place is captured entirely, so doesn't matter if needs dtor, it will be drop
734734 // when the closure is dropped.
735735 return false ;
736736 }
737737
738+ if captured_by_move_projs. is_empty ( ) {
739+ return needs_drop ( base_path_ty) ;
740+ }
741+
738742 if is_drop_defined_for_ty {
739743 // 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.
744745
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 ;
747751 }
748752
749753 match base_path_ty. kind ( ) {
750754 // 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.
755759
756760 // We don't capture derefs in case of move captures, which would have be applied to
757761 // access any further paths.
@@ -761,19 +765,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
761765
762766 ty:: Adt ( def, substs) => {
763767 // 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 `.
765769 assert_eq ! ( def. variants. len( ) , 1 ) ;
766770
767771 // Only Field projections can be applied to a non-box Adt.
768772 assert ! (
769- captured_projs . iter( ) . all( |projs| matches!(
773+ captured_by_move_projs . iter( ) . all( |projs| matches!(
770774 projs. first( ) . unwrap( ) . kind,
771775 ProjectionKind :: Field ( ..)
772776 ) )
773777 ) ;
774778 def. variants . get ( VariantIdx :: new ( 0 ) ) . unwrap ( ) . fields . iter ( ) . enumerate ( ) . any (
775779 |( i, field) | {
776- let paths_using_field = captured_projs
780+ let paths_using_field = captured_by_move_projs
777781 . iter ( )
778782 . filter_map ( |projs| {
779783 if let ProjectionKind :: Field ( field_idx, _) =
@@ -800,14 +804,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
800804 ty:: Tuple ( ..) => {
801805 // Only Field projections can be applied to a tuple.
802806 assert ! (
803- captured_projs . iter( ) . all( |projs| matches!(
807+ captured_by_move_projs . iter( ) . all( |projs| matches!(
804808 projs. first( ) . unwrap( ) . kind,
805809 ProjectionKind :: Field ( ..)
806810 ) )
807811 ) ;
808812
809813 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
811815 . iter ( )
812816 . filter_map ( |projs| {
813817 if let ProjectionKind :: Field ( field_idx, _) = projs. first ( ) . unwrap ( ) . kind
0 commit comments