Skip to content

Commit 4f93357

Browse files
committed
Auto merge of #47607 - davidtwco:issue-45697, r=nikomatsakis
MIR-borrowck: augmented assignment causes duplicate errors Fixes #45697. This PR resolves the error duplication. I attempted to replace the existing sets since there were quite a few but only managed to replace two of them. r? @nikomatsakis
2 parents bd98fe0 + bb6e54d commit 4f93357

File tree

7 files changed

+150
-48
lines changed

7 files changed

+150
-48
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

+8-21
Original file line numberDiff line numberDiff line change
@@ -362,33 +362,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
362362
let scope_tree = borrows.0.scope_tree();
363363
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
364364

365-
match root_place {
366-
&Place::Local(local) => {
367-
if let Some(_) = self.storage_dead_or_drop_error_reported_l.replace(local) {
368-
debug!("report_does_not_live_long_enough({:?}): <suppressed>",
369-
(borrow, drop_span));
370-
return
371-
}
372-
}
373-
&Place::Static(ref statik) => {
374-
if let Some(_) = self.storage_dead_or_drop_error_reported_s
375-
.replace(statik.def_id)
376-
{
377-
debug!("report_does_not_live_long_enough({:?}): <suppressed>",
378-
(borrow, drop_span));
379-
return
380-
}
381-
},
382-
&Place::Projection(_) =>
383-
unreachable!("root_place is an unreachable???")
384-
};
385-
386365
let borrow_span = self.mir.source_info(borrow.location).span;
387366
let proper_span = match *root_place {
388367
Place::Local(local) => self.mir.local_decls[local].source_info.span,
389368
_ => drop_span,
390369
};
391370

371+
if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) {
372+
debug!("suppressing access_place error when borrow doesn't live long enough for {:?}",
373+
borrow_span);
374+
return;
375+
}
376+
377+
self.access_place_error_reported.insert((root_place.clone(), borrow_span));
378+
392379
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
393380
(RegionKind::ReScope(_), Some(name)) => {
394381
self.report_scoped_local_value_does_not_live_long_enough(

src/librustc_mir/borrow_check/mod.rs

+35-25
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::hir::map::definitions::DefPathData;
1717
use rustc::infer::InferCtxt;
1818
use rustc::ty::{self, ParamEnv, TyCtxt};
1919
use rustc::ty::maps::Providers;
20-
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Local, Location, Place};
20+
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place};
2121
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
2222
use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
2323
use rustc::mir::ClosureRegionRequirements;
@@ -228,8 +228,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
228228
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
229229
hir::BodyOwnerKind::Fn => true,
230230
},
231-
storage_dead_or_drop_error_reported_l: FxHashSet(),
232-
storage_dead_or_drop_error_reported_s: FxHashSet(),
231+
access_place_error_reported: FxHashSet(),
233232
reservation_error_reported: FxHashSet(),
234233
nonlexical_regioncx: opt_regioncx.clone(),
235234
};
@@ -294,12 +293,12 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
294293
/// I'm not sure this is the right approach - @eddyb could you try and
295294
/// figure this out?
296295
locals_are_invalidated_at_exit: bool,
297-
/// This field keeps track of when storage dead or drop errors are reported
298-
/// in order to stop duplicate error reporting and identify the conditions required
299-
/// for a "temporary value dropped here while still borrowed" error. See #45360.
300-
storage_dead_or_drop_error_reported_l: FxHashSet<Local>,
301-
/// Same as the above, but for statics (thread-locals)
302-
storage_dead_or_drop_error_reported_s: FxHashSet<DefId>,
296+
/// This field keeps track of when borrow errors are reported in the access_place function
297+
/// so that there is no duplicate reporting. This field cannot also be used for the conflicting
298+
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
299+
/// of the `Span` type (while required to mute some errors) stops the muting of the reservation
300+
/// errors.
301+
access_place_error_reported: FxHashSet<(Place<'tcx>, Span)>,
303302
/// This field keeps track of when borrow conflict errors are reported
304303
/// for reservations, so that we don't report seemingly duplicate
305304
/// errors for corresponding activations
@@ -348,20 +347,20 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
348347

349348
match stmt.kind {
350349
StatementKind::Assign(ref lhs, ref rhs) => {
350+
self.consume_rvalue(
351+
ContextKind::AssignRhs.new(location),
352+
(rhs, span),
353+
location,
354+
flow_state,
355+
);
356+
351357
self.mutate_place(
352358
ContextKind::AssignLhs.new(location),
353359
(lhs, span),
354360
Shallow(None),
355361
JustWrite,
356362
flow_state,
357363
);
358-
359-
self.consume_rvalue(
360-
ContextKind::AssignRhs.new(location),
361-
(rhs, span),
362-
location,
363-
flow_state,
364-
);
365364
}
366365
StatementKind::SetDiscriminant {
367366
ref place,
@@ -726,24 +725,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
726725

727726
if let Activation(_, borrow_index) = rw {
728727
if self.reservation_error_reported.contains(&place_span.0) {
729-
debug!(
730-
"skipping access_place for activation of invalid reservation \
731-
place: {:?} borrow_index: {:?}",
732-
place_span.0,
733-
borrow_index
734-
);
728+
debug!("skipping access_place for activation of invalid reservation \
729+
place: {:?} borrow_index: {:?}", place_span.0, borrow_index);
735730
return AccessErrorsReported {
736731
mutability_error: false,
737732
conflict_error: true,
738733
};
739734
}
740735
}
741736

737+
if self.access_place_error_reported.contains(&(place_span.0.clone(), place_span.1)) {
738+
debug!("access_place: suppressing error place_span=`{:?}` kind=`{:?}`",
739+
place_span, kind);
740+
return AccessErrorsReported {
741+
mutability_error: false,
742+
conflict_error: true,
743+
};
744+
}
745+
742746
let mutability_error =
743747
self.check_access_permissions(place_span, rw, is_local_mutation_allowed);
744748
let conflict_error =
745749
self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
746750

751+
if conflict_error || mutability_error {
752+
debug!("access_place: logging error place_span=`{:?}` kind=`{:?}`",
753+
place_span, kind);
754+
self.access_place_error_reported.insert((place_span.0.clone(), place_span.1));
755+
}
756+
747757
AccessErrorsReported {
748758
mutability_error,
749759
conflict_error,
@@ -829,15 +839,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
829839
place_span.0
830840
);
831841
this.reservation_error_reported.insert(place_span.0.clone());
832-
}
842+
},
833843
Activation(_, activating) => {
834844
debug!(
835845
"observing check_place for activation of \
836846
borrow_index: {:?}",
837847
activating
838848
);
839-
}
840-
Read(..) | Write(..) => {}
849+
},
850+
Read(..) | Write(..) => {},
841851
}
842852

843853
match kind {

src/test/compile-fail/nll/reference-carried-through-struct-field.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ fn foo() {
1919
let mut x = 22;
2020
let wrapper = Wrap { w: &mut x };
2121
x += 1; //[ast]~ ERROR cannot assign to `x` because it is borrowed [E0506]
22-
//[mir]~^ ERROR cannot assign to `x` because it is borrowed [E0506]
23-
//[mir]~^^ ERROR cannot use `x` because it was mutably borrowed [E0503]
22+
//[mir]~^ ERROR cannot use `x` because it was mutably borrowed [E0503]
2423
*wrapper.w += 1;
2524
}
2625

src/test/ui/issue-45697-1.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that assignments to an `&mut` pointer which is found in a
12+
// borrowed (but otherwise non-aliasable) location is illegal.
13+
14+
// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=on
15+
16+
struct S<'a> {
17+
pointer: &'a mut isize
18+
}
19+
20+
fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
21+
S { pointer: &mut *p.pointer }
22+
}
23+
24+
fn main() {
25+
let mut x = 1;
26+
27+
{
28+
let mut y = S { pointer: &mut x };
29+
let z = copy_borrowed_ptr(&mut y);
30+
*y.pointer += 1;
31+
//~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
32+
//~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
33+
*z.pointer += 1;
34+
}
35+
}

src/test/ui/issue-45697-1.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
2+
--> $DIR/issue-45697-1.rs:30:9
3+
|
4+
29 | let z = copy_borrowed_ptr(&mut y);
5+
| - borrow of `*y.pointer` occurs here
6+
30 | *y.pointer += 1;
7+
| ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
8+
9+
error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
10+
--> $DIR/issue-45697-1.rs:30:9
11+
|
12+
29 | let z = copy_borrowed_ptr(&mut y);
13+
| ------ borrow of `y` occurs here
14+
30 | *y.pointer += 1;
15+
| ^^^^^^^^^^^^^^^ use of borrowed `y`
16+
17+
error: aborting due to 2 previous errors
18+

src/test/ui/issue-45697.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that assignments to an `&mut` pointer which is found in a
12+
// borrowed (but otherwise non-aliasable) location is illegal.
13+
14+
// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=off
15+
16+
struct S<'a> {
17+
pointer: &'a mut isize
18+
}
19+
20+
fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
21+
S { pointer: &mut *p.pointer }
22+
}
23+
24+
fn main() {
25+
let mut x = 1;
26+
27+
{
28+
let mut y = S { pointer: &mut x };
29+
let z = copy_borrowed_ptr(&mut y);
30+
*y.pointer += 1;
31+
//~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506]
32+
//~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503]
33+
*z.pointer += 1;
34+
}
35+
}

src/test/ui/issue-45697.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
2+
--> $DIR/issue-45697.rs:30:9
3+
|
4+
29 | let z = copy_borrowed_ptr(&mut y);
5+
| - borrow of `*y.pointer` occurs here
6+
30 | *y.pointer += 1;
7+
| ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
8+
9+
error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
10+
--> $DIR/issue-45697.rs:30:9
11+
|
12+
29 | let z = copy_borrowed_ptr(&mut y);
13+
| ------ borrow of `y` occurs here
14+
30 | *y.pointer += 1;
15+
| ^^^^^^^^^^^^^^^ use of borrowed `y`
16+
17+
error: aborting due to 2 previous errors
18+

0 commit comments

Comments
 (0)