@@ -174,7 +174,7 @@ fn do_mir_borrowck<'a, 'tcx>(
174174
175175 let mut errors_buffer = Vec :: new ( ) ;
176176 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 ) {
178178 Ok ( move_data) => ( move_data, None ) ,
179179 Err ( ( move_data, move_errors) ) => ( move_data, Some ( move_errors) ) ,
180180 } ;
@@ -1600,7 +1600,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16001600 ( prefix, place_span. 0 , place_span. 1 ) ,
16011601 mpi,
16021602 ) ;
1603- return ; // don't bother finding other problems.
16041603 }
16051604 }
16061605 Err ( NoMovePathFound :: ReachedStatic ) => {
@@ -1614,6 +1613,46 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16141613 }
16151614 }
16161615
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+
16171656 fn check_if_path_or_subpath_is_moved (
16181657 & mut self ,
16191658 location : Location ,
@@ -1640,6 +1679,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16401679
16411680 self . check_if_full_path_is_moved ( location, desired_action, place_span, flow_state) ;
16421681
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+
16431706 // A move of any shallow suffix of `place` also interferes
16441707 // with an attempt to use `place`. This is scenario 3 above.
16451708 //
@@ -1675,25 +1738,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16751738 /// static variable, as we do not track those in the MoveData.
16761739 fn move_path_closest_to (
16771740 & mut self ,
1678- place : PlaceRef < ' cx , ' tcx > ,
1741+ place : PlaceRef < ' _ , ' tcx > ,
16791742 ) -> 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 ) ,
16931747 }
16941748 }
16951749
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 > {
16971751 // If returns None, then there is no move path corresponding
16981752 // to a direct owner of `place` (which means there is nothing
16991753 // that borrowck tracks for its analysis).
0 commit comments