@@ -18,12 +18,13 @@ use rustc::ty::{self, TyCtxt};
1818
1919use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , Level } ;
2020use rustc_data_structures:: bit_set:: BitSet ;
21- use rustc_data_structures:: fx:: FxHashSet ;
21+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
2222use rustc_data_structures:: graph:: dominators:: Dominators ;
2323use smallvec:: SmallVec ;
2424
25- use std:: rc:: Rc ;
2625use std:: collections:: BTreeMap ;
26+ use std:: mem;
27+ use std:: rc:: Rc ;
2728
2829use syntax_pos:: Span ;
2930
@@ -238,6 +239,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
238239 locals_are_invalidated_at_exit,
239240 access_place_error_reported : Default :: default ( ) ,
240241 reservation_error_reported : Default :: default ( ) ,
242+ reservation_warnings : Default :: default ( ) ,
241243 move_error_reported : BTreeMap :: new ( ) ,
242244 uninitialized_error_reported : Default :: default ( ) ,
243245 errors_buffer,
@@ -260,6 +262,14 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
260262 }
261263 mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
262264
265+ // Buffer any reservation warnings.
266+ let reservation_warnings = mem:: replace ( & mut mbcx. reservation_warnings , Default :: default ( ) ) ;
267+ for ( _, ( place, span, context, bk, borrow) ) in reservation_warnings {
268+ let mut diag = mbcx. report_conflicting_borrow ( context, ( & place, span) , bk, & borrow) ;
269+ downgrade_if_error ( & mut diag) ;
270+ diag. buffer ( & mut mbcx. errors_buffer ) ;
271+ }
272+
263273 // For each non-user used mutable variable, check if it's been assigned from
264274 // a user-declared local. If so, then put that local into the used_mut set.
265275 // Note that this set is expected to be small - only upvars from closures
@@ -341,18 +351,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
341351 // if AST-borrowck signalled no errors, then
342352 // downgrade all the buffered MIR-borrowck errors
343353 // to warnings.
344- for err in & mut mbcx. errors_buffer {
345- if err. is_error ( ) {
346- err. level = Level :: Warning ;
347- err. warn (
348- "this error has been downgraded to a warning for backwards \
349- compatibility with previous releases",
350- ) ;
351- err. warn (
352- "this represents potential undefined behavior in your code and \
353- this warning will become a hard error in the future",
354- ) ;
355- }
354+
355+ for err in mbcx. errors_buffer . iter_mut ( ) {
356+ downgrade_if_error ( err) ;
356357 }
357358 }
358359 SignalledError :: SawSomeError => {
@@ -378,6 +379,20 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
378379 result
379380}
380381
382+ fn downgrade_if_error ( diag : & mut Diagnostic ) {
383+ if diag. is_error ( ) {
384+ diag. level = Level :: Warning ;
385+ diag. warn (
386+ "this error has been downgraded to a warning for backwards \
387+ compatibility with previous releases",
388+ ) ;
389+ diag. warn (
390+ "this represents potential undefined behavior in your code and \
391+ this warning will become a hard error in the future",
392+ ) ;
393+ }
394+ }
395+
381396pub struct MirBorrowckCtxt < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
382397 infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
383398 mir : & ' cx Mir < ' tcx > ,
@@ -410,6 +425,13 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
410425 // but it is currently inconvenient to track down the `BorrowIndex`
411426 // at the time we detect and report a reservation error.
412427 reservation_error_reported : FxHashSet < Place < ' tcx > > ,
428+ /// Migration warnings to be reported for #56254. We delay reporting these
429+ /// so that we can suppress the warning if there's a corresponding error
430+ /// for the activation of the borrow.
431+ reservation_warnings : FxHashMap <
432+ BorrowIndex ,
433+ ( Place < ' tcx > , Span , Context , BorrowKind , BorrowData < ' tcx > )
434+ > ,
413435 /// This field keeps track of move errors that are to be reported for given move indicies.
414436 ///
415437 /// There are situations where many errors can be reported for a single move out (see #53807)
@@ -921,11 +943,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
921943 let conflict_error =
922944 self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
923945
946+ if let ( Activation ( _, borrow_idx) , true ) = ( kind. 1 , conflict_error) {
947+ // Suppress this warning when there's an error being emited for the
948+ // same borrow: fixing the error is likely to fix the warning.
949+ self . reservation_warnings . remove ( & borrow_idx) ;
950+ }
951+
924952 if conflict_error || mutability_error {
925953 debug ! (
926954 "access_place: logging error place_span=`{:?}` kind=`{:?}`" ,
927955 place_span, kind
928956 ) ;
957+
929958 self . access_place_error_reported
930959 . insert ( ( place_span. 0 . clone ( ) , place_span. 1 ) ) ;
931960 }
@@ -976,8 +1005,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9761005 Control :: Continue
9771006 }
9781007
979- ( Read ( _) , BorrowKind :: Shared ) | ( Reservation ( .. ) , BorrowKind :: Shared )
980- | ( Read ( _) , BorrowKind :: Shallow ) | ( Reservation ( .. ) , BorrowKind :: Shallow )
1008+ ( Read ( _) , BorrowKind :: Shared )
1009+ | ( Read ( _) , BorrowKind :: Shallow )
9811010 | ( Read ( ReadKind :: Borrow ( BorrowKind :: Shallow ) ) , BorrowKind :: Unique )
9821011 | ( Read ( ReadKind :: Borrow ( BorrowKind :: Shallow ) ) , BorrowKind :: Mut { .. } ) => {
9831012 Control :: Continue
@@ -991,28 +1020,53 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9911020 ( Read ( kind) , BorrowKind :: Unique ) | ( Read ( kind) , BorrowKind :: Mut { .. } ) => {
9921021 // Reading from mere reservations of mutable-borrows is OK.
9931022 if !is_active ( & this. dominators , borrow, context. loc ) {
994- assert ! ( allow_two_phase_borrow( & this . infcx . tcx, borrow. kind) ) ;
1023+ assert ! ( allow_two_phase_borrow( & tcx, borrow. kind) ) ;
9951024 return Control :: Continue ;
9961025 }
9971026
9981027 error_reported = true ;
9991028 match kind {
10001029 ReadKind :: Copy => {
10011030 this. report_use_while_mutably_borrowed ( context, place_span, borrow)
1031+ . buffer ( & mut this. errors_buffer ) ;
10021032 }
10031033 ReadKind :: Borrow ( bk) => {
1004- this. report_conflicting_borrow ( context, place_span, bk, & borrow)
1034+ this. report_conflicting_borrow ( context, place_span, bk, borrow)
1035+ . buffer ( & mut this. errors_buffer ) ;
10051036 }
10061037 }
10071038 Control :: Break
10081039 }
10091040
1010- ( Reservation ( kind) , BorrowKind :: Unique )
1011- | ( Reservation ( kind) , BorrowKind :: Mut { .. } )
1041+ ( Reservation ( WriteKind :: MutableBorrow ( bk) ) , BorrowKind :: Shallow )
1042+ | ( Reservation ( WriteKind :: MutableBorrow ( bk) ) , BorrowKind :: Shared ) if {
1043+ tcx. migrate_borrowck ( )
1044+ } => {
1045+ let bi = this. borrow_set . location_map [ & context. loc ] ;
1046+ debug ! (
1047+ "recording invalid reservation of place: {:?} with \
1048+ borrow index {:?} as warning",
1049+ place_span. 0 ,
1050+ bi,
1051+ ) ;
1052+ // rust-lang/rust#56254 - This was previously permitted on
1053+ // the 2018 edition so we emit it as a warning. We buffer
1054+ // these sepately so that we only emit a warning if borrow
1055+ // checking was otherwise successful.
1056+ this. reservation_warnings . insert (
1057+ bi,
1058+ ( place_span. 0 . clone ( ) , place_span. 1 , context, bk, borrow. clone ( ) ) ,
1059+ ) ;
1060+
1061+ // Don't suppress actual errors.
1062+ Control :: Continue
1063+ }
1064+
1065+ ( Reservation ( kind) , _)
10121066 | ( Activation ( kind, _) , _)
10131067 | ( Write ( kind) , _) => {
10141068 match rw {
1015- Reservation ( _ ) => {
1069+ Reservation ( .. ) => {
10161070 debug ! (
10171071 "recording invalid reservation of \
10181072 place: {:?}",
@@ -1033,7 +1087,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10331087 error_reported = true ;
10341088 match kind {
10351089 WriteKind :: MutableBorrow ( bk) => {
1036- this. report_conflicting_borrow ( context, place_span, bk, & borrow)
1090+ this. report_conflicting_borrow ( context, place_span, bk, borrow)
1091+ . buffer ( & mut this. errors_buffer ) ;
10371092 }
10381093 WriteKind :: StorageDeadOrDrop => {
10391094 this. report_borrowed_value_does_not_live_long_enough (
@@ -1046,7 +1101,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10461101 this. report_illegal_mutation_of_borrowed ( context, place_span, borrow)
10471102 }
10481103 WriteKind :: Move => {
1049- this. report_move_out_while_borrowed ( context, place_span, & borrow)
1104+ this. report_move_out_while_borrowed ( context, place_span, borrow)
10501105 }
10511106 }
10521107 Control :: Break
0 commit comments