@@ -18,12 +18,13 @@ use rustc::ty::{self, TyCtxt};
18
18
19
19
use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , Level } ;
20
20
use rustc_data_structures:: bit_set:: BitSet ;
21
- use rustc_data_structures:: fx:: FxHashSet ;
21
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
22
22
use rustc_data_structures:: graph:: dominators:: Dominators ;
23
23
use smallvec:: SmallVec ;
24
24
25
- use std:: rc:: Rc ;
26
25
use std:: collections:: BTreeMap ;
26
+ use std:: mem;
27
+ use std:: rc:: Rc ;
27
28
28
29
use syntax_pos:: Span ;
29
30
@@ -238,6 +239,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
238
239
locals_are_invalidated_at_exit,
239
240
access_place_error_reported : Default :: default ( ) ,
240
241
reservation_error_reported : Default :: default ( ) ,
242
+ reservation_warnings : Default :: default ( ) ,
241
243
move_error_reported : BTreeMap :: new ( ) ,
242
244
uninitialized_error_reported : Default :: default ( ) ,
243
245
errors_buffer,
@@ -260,6 +262,14 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
260
262
}
261
263
mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
262
264
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
+
263
273
// For each non-user used mutable variable, check if it's been assigned from
264
274
// a user-declared local. If so, then put that local into the used_mut set.
265
275
// Note that this set is expected to be small - only upvars from closures
@@ -341,18 +351,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
341
351
// if AST-borrowck signalled no errors, then
342
352
// downgrade all the buffered MIR-borrowck errors
343
353
// 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) ;
356
357
}
357
358
}
358
359
SignalledError :: SawSomeError => {
@@ -378,6 +379,20 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
378
379
result
379
380
}
380
381
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
+
381
396
pub struct MirBorrowckCtxt < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
382
397
infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
383
398
mir : & ' cx Mir < ' tcx > ,
@@ -410,6 +425,13 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
410
425
// but it is currently inconvenient to track down the `BorrowIndex`
411
426
// at the time we detect and report a reservation error.
412
427
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
+ > ,
413
435
/// This field keeps track of move errors that are to be reported for given move indicies.
414
436
///
415
437
/// 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> {
921
943
let conflict_error =
922
944
self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
923
945
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
+
924
952
if conflict_error || mutability_error {
925
953
debug ! (
926
954
"access_place: logging error place_span=`{:?}` kind=`{:?}`" ,
927
955
place_span, kind
928
956
) ;
957
+
929
958
self . access_place_error_reported
930
959
. insert ( ( place_span. 0 . clone ( ) , place_span. 1 ) ) ;
931
960
}
@@ -976,8 +1005,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
976
1005
Control :: Continue
977
1006
}
978
1007
979
- ( Read ( _) , BorrowKind :: Shared ) | ( Reservation ( .. ) , BorrowKind :: Shared )
980
- | ( Read ( _) , BorrowKind :: Shallow ) | ( Reservation ( .. ) , BorrowKind :: Shallow )
1008
+ ( Read ( _) , BorrowKind :: Shared )
1009
+ | ( Read ( _) , BorrowKind :: Shallow )
981
1010
| ( Read ( ReadKind :: Borrow ( BorrowKind :: Shallow ) ) , BorrowKind :: Unique )
982
1011
| ( Read ( ReadKind :: Borrow ( BorrowKind :: Shallow ) ) , BorrowKind :: Mut { .. } ) => {
983
1012
Control :: Continue
@@ -991,28 +1020,53 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
991
1020
( Read ( kind) , BorrowKind :: Unique ) | ( Read ( kind) , BorrowKind :: Mut { .. } ) => {
992
1021
// Reading from mere reservations of mutable-borrows is OK.
993
1022
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) ) ;
995
1024
return Control :: Continue ;
996
1025
}
997
1026
998
1027
error_reported = true ;
999
1028
match kind {
1000
1029
ReadKind :: Copy => {
1001
1030
this. report_use_while_mutably_borrowed ( context, place_span, borrow)
1031
+ . buffer ( & mut this. errors_buffer ) ;
1002
1032
}
1003
1033
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 ) ;
1005
1036
}
1006
1037
}
1007
1038
Control :: Break
1008
1039
}
1009
1040
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) , _)
1012
1066
| ( Activation ( kind, _) , _)
1013
1067
| ( Write ( kind) , _) => {
1014
1068
match rw {
1015
- Reservation ( _ ) => {
1069
+ Reservation ( .. ) => {
1016
1070
debug ! (
1017
1071
"recording invalid reservation of \
1018
1072
place: {:?}",
@@ -1033,7 +1087,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1033
1087
error_reported = true ;
1034
1088
match kind {
1035
1089
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 ) ;
1037
1092
}
1038
1093
WriteKind :: StorageDeadOrDrop => {
1039
1094
this. report_borrowed_value_does_not_live_long_enough (
@@ -1046,7 +1101,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1046
1101
this. report_illegal_mutation_of_borrowed ( context, place_span, borrow)
1047
1102
}
1048
1103
WriteKind :: Move => {
1049
- this. report_move_out_while_borrowed ( context, place_span, & borrow)
1104
+ this. report_move_out_while_borrowed ( context, place_span, borrow)
1050
1105
}
1051
1106
}
1052
1107
Control :: Break
0 commit comments