@@ -174,7 +174,7 @@ fn do_mir_borrowck<'a, 'tcx>(
174
174
175
175
let mut errors_buffer = Vec :: new ( ) ;
176
176
let ( move_data, move_errors) : ( MoveData < ' tcx > , Option < Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > > ) =
177
- match MoveData :: gather_moves ( & body, tcx) {
177
+ match MoveData :: gather_moves ( & body, tcx, param_env ) {
178
178
Ok ( move_data) => ( move_data, None ) ,
179
179
Err ( ( move_data, move_errors) ) => ( move_data, Some ( move_errors) ) ,
180
180
} ;
@@ -1600,7 +1600,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1600
1600
( prefix, place_span. 0 , place_span. 1 ) ,
1601
1601
mpi,
1602
1602
) ;
1603
- return ; // don't bother finding other problems.
1604
1603
}
1605
1604
}
1606
1605
Err ( NoMovePathFound :: ReachedStatic ) => {
@@ -1614,6 +1613,46 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1614
1613
}
1615
1614
}
1616
1615
1616
+ /// Subslices correspond to multiple move paths, so we iterate through the
1617
+ /// elements of the base array. For each element we check
1618
+ ///
1619
+ /// * Does this element overlap with our slice.
1620
+ /// * Is any part of it uninitialized.
1621
+ fn check_if_subslice_element_is_moved (
1622
+ & mut self ,
1623
+ location : Location ,
1624
+ desired_action : InitializationRequiringAction ,
1625
+ place_span : ( PlaceRef < ' cx , ' tcx > , Span ) ,
1626
+ maybe_uninits : & FlowAtLocation < ' tcx , MaybeUninitializedPlaces < ' cx , ' tcx > > ,
1627
+ from : u32 ,
1628
+ to : u32 ,
1629
+ ) {
1630
+ if let Some ( mpi) = self . move_path_for_place ( place_span. 0 ) {
1631
+ let mut child = self . move_data . move_paths [ mpi] . first_child ;
1632
+ while let Some ( child_mpi) = child {
1633
+ let child_move_place = & self . move_data . move_paths [ child_mpi] ;
1634
+ let child_place = & child_move_place. place ;
1635
+ let last_proj = child_place. projection . last ( ) . unwrap ( ) ;
1636
+ if let ProjectionElem :: ConstantIndex { offset, from_end, .. } = last_proj {
1637
+ debug_assert ! ( !from_end, "Array constant indexing shouldn't be `from_end`." ) ;
1638
+
1639
+ if ( from..to) . contains ( offset) {
1640
+ if let Some ( uninit_child) = maybe_uninits. has_any_child_of ( child_mpi) {
1641
+ self . report_use_of_moved_or_uninitialized (
1642
+ location,
1643
+ desired_action,
1644
+ ( place_span. 0 , place_span. 0 , place_span. 1 ) ,
1645
+ uninit_child,
1646
+ ) ;
1647
+ return ; // don't bother finding other problems.
1648
+ }
1649
+ }
1650
+ }
1651
+ child = child_move_place. next_sibling ;
1652
+ }
1653
+ }
1654
+ }
1655
+
1617
1656
fn check_if_path_or_subpath_is_moved (
1618
1657
& mut self ,
1619
1658
location : Location ,
@@ -1640,6 +1679,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1640
1679
1641
1680
self . check_if_full_path_is_moved ( location, desired_action, place_span, flow_state) ;
1642
1681
1682
+ if let [
1683
+ base_proj @ ..,
1684
+ ProjectionElem :: Subslice { from, to, from_end : false } ,
1685
+ ] = place_span. 0 . projection {
1686
+ let place_ty = Place :: ty_from (
1687
+ place_span. 0 . base ,
1688
+ base_proj,
1689
+ self . body ( ) ,
1690
+ self . infcx . tcx ,
1691
+ ) ;
1692
+ if let ty:: Array ( ..) = place_ty. ty . kind {
1693
+ let array_place = PlaceRef { base : place_span. 0 . base , projection : base_proj } ;
1694
+ self . check_if_subslice_element_is_moved (
1695
+ location,
1696
+ desired_action,
1697
+ ( array_place, place_span. 1 ) ,
1698
+ maybe_uninits,
1699
+ * from,
1700
+ * to,
1701
+ ) ;
1702
+ return ;
1703
+ }
1704
+ }
1705
+
1643
1706
// A move of any shallow suffix of `place` also interferes
1644
1707
// with an attempt to use `place`. This is scenario 3 above.
1645
1708
//
@@ -1675,25 +1738,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1675
1738
/// static variable, as we do not track those in the MoveData.
1676
1739
fn move_path_closest_to (
1677
1740
& mut self ,
1678
- place : PlaceRef < ' cx , ' tcx > ,
1741
+ place : PlaceRef < ' _ , ' tcx > ,
1679
1742
) -> Result < ( PlaceRef < ' cx , ' tcx > , MovePathIndex ) , NoMovePathFound > {
1680
- let mut last_prefix = place. base ;
1681
-
1682
- for prefix in self . prefixes ( place, PrefixSet :: All ) {
1683
- if let Some ( mpi) = self . move_path_for_place ( prefix) {
1684
- return Ok ( ( prefix, mpi) ) ;
1685
- }
1686
-
1687
- last_prefix = prefix. base ;
1688
- }
1689
-
1690
- match last_prefix {
1691
- PlaceBase :: Local ( _) => panic ! ( "should have move path for every Local" ) ,
1692
- PlaceBase :: Static ( _) => Err ( NoMovePathFound :: ReachedStatic ) ,
1743
+ match self . move_data . rev_lookup . find ( place) {
1744
+ LookupResult :: Parent ( Some ( mpi) )
1745
+ | LookupResult :: Exact ( mpi) => Ok ( ( self . move_data . move_paths [ mpi] . place . as_ref ( ) , mpi) ) ,
1746
+ LookupResult :: Parent ( None ) => Err ( NoMovePathFound :: ReachedStatic ) ,
1693
1747
}
1694
1748
}
1695
1749
1696
- fn move_path_for_place ( & mut self , place : PlaceRef < ' cx , ' tcx > ) -> Option < MovePathIndex > {
1750
+ fn move_path_for_place ( & mut self , place : PlaceRef < ' _ , ' tcx > ) -> Option < MovePathIndex > {
1697
1751
// If returns None, then there is no move path corresponding
1698
1752
// to a direct owner of `place` (which means there is nothing
1699
1753
// that borrowck tracks for its analysis).
0 commit comments