Skip to content

Commit b1409af

Browse files
committed
Auto merge of #46032 - KiChjang:ignore-borrowck-statics, r=nikomatsakis
Ignore borrowck for static lvalues and allow assignment to static muts Fixes #45129. Fixes #45641.
2 parents 1f491e0 + f8ba371 commit b1409af

File tree

5 files changed

+108
-44
lines changed

5 files changed

+108
-44
lines changed

src/librustc_mir/borrow_check.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -707,10 +707,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
707707
Mutability::Mut => return,
708708
}
709709
}
710-
Lvalue::Static(_) => {
710+
Lvalue::Static(ref static_) => {
711711
// mutation of non-mut static is always illegal,
712712
// independent of dataflow.
713-
self.report_assignment_to_static(context, (lvalue, span));
713+
if !self.tcx.is_static_mut(static_.def_id) {
714+
self.report_assignment_to_static(context, (lvalue, span));
715+
}
714716
return;
715717
}
716718
}

src/librustc_mir/dataflow/impls/borrows.rs

+50-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use rustc::mir::{self, Location, Mir};
1212
use rustc::mir::visit::Visitor;
13-
use rustc::ty::{Region, TyCtxt};
13+
use rustc::ty::{self, Region, TyCtxt};
1414
use rustc::ty::RegionKind;
1515
use rustc::ty::RegionKind::ReScope;
1616
use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -71,10 +71,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
7171
mir: &'a Mir<'tcx>,
7272
nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
7373
-> Self {
74-
let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
75-
location_map: FxHashMap(),
76-
region_map: FxHashMap(),
77-
region_span_map: FxHashMap()};
74+
let mut visitor = GatherBorrows {
75+
tcx,
76+
mir,
77+
idx_vec: IndexVec::new(),
78+
location_map: FxHashMap(),
79+
region_map: FxHashMap(),
80+
region_span_map: FxHashMap()
81+
};
7882
visitor.visit_mir(mir);
7983
return Borrows { tcx: tcx,
8084
mir: mir,
@@ -84,17 +88,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
8488
region_span_map: visitor.region_span_map,
8589
nonlexical_regioncx };
8690

87-
struct GatherBorrows<'tcx> {
91+
struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
92+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
93+
mir: &'a Mir<'tcx>,
8894
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
8995
location_map: FxHashMap<Location, BorrowIndex>,
9096
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
9197
region_span_map: FxHashMap<RegionKind, Span>,
9298
}
93-
impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
99+
100+
impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
94101
fn visit_rvalue(&mut self,
95102
rvalue: &mir::Rvalue<'tcx>,
96103
location: mir::Location) {
97104
if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
105+
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
106+
98107
let borrow = BorrowData {
99108
location: location, kind: kind, region: region, lvalue: lvalue.clone(),
100109
};
@@ -197,7 +206,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
197206
}
198207

199208
mir::StatementKind::Assign(_, ref rhs) => {
200-
if let mir::Rvalue::Ref(region, _, _) = *rhs {
209+
if let mir::Rvalue::Ref(region, _, ref lvalue) = *rhs {
210+
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
201211
let index = self.location_map.get(&location).unwrap_or_else(|| {
202212
panic!("could not find BorrowIndex for location {:?}", location);
203213
});
@@ -248,3 +258,35 @@ impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
248258
false // bottom = no Rvalue::Refs are active by default
249259
}
250260
}
261+
262+
fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
263+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
264+
mir: &'a Mir<'tcx>,
265+
lvalue: &mir::Lvalue<'tcx>
266+
) -> bool {
267+
use self::mir::Lvalue::*;
268+
use self::mir::ProjectionElem;
269+
270+
match *lvalue {
271+
Local(_) => false,
272+
Static(ref static_) => tcx.is_static_mut(static_.def_id),
273+
Projection(ref proj) => {
274+
match proj.elem {
275+
ProjectionElem::Field(..) |
276+
ProjectionElem::Downcast(..) |
277+
ProjectionElem::Subslice { .. } |
278+
ProjectionElem::ConstantIndex { .. } |
279+
ProjectionElem::Index(_) => {
280+
is_unsafe_lvalue(tcx, mir, &proj.base)
281+
}
282+
ProjectionElem::Deref => {
283+
let ty = proj.base.ty(mir, tcx).to_ty(tcx);
284+
match ty.sty {
285+
ty::TyRawPtr(..) => true,
286+
_ => is_unsafe_lvalue(tcx, mir, &proj.base),
287+
}
288+
}
289+
}
290+
}
291+
}
292+
}

src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs

-34
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ impl Baz {
4646
}
4747
}
4848

49-
static mut sfoo : Foo = Foo{x: 23 };
50-
static mut sbar : Bar = Bar(23);
51-
static mut stuple : (i32, i32) = (24, 25);
52-
static mut senum : Baz = Baz::X(26);
53-
static mut sunion : U = U { a: 0 };
54-
5549
fn main() {
5650
// Local and field from struct
5751
{
@@ -96,34 +90,6 @@ fn main() {
9690
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
9791
//[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
9892
}
99-
// Static and field from struct
100-
unsafe {
101-
let _x = sfoo.x();
102-
sfoo.x; //[mir]~ ERROR cannot use `sfoo.x` because it was mutably borrowed (Mir)
103-
}
104-
// Static and field from tuple-struct
105-
unsafe {
106-
let _0 = sbar.x();
107-
sbar.0; //[mir]~ ERROR cannot use `sbar.0` because it was mutably borrowed (Mir)
108-
}
109-
// Static and field from tuple
110-
unsafe {
111-
let _0 = &mut stuple.0;
112-
stuple.0; //[mir]~ ERROR cannot use `stuple.0` because it was mutably borrowed (Mir)
113-
}
114-
// Static and field from enum
115-
unsafe {
116-
let _e0 = senum.x();
117-
match senum {
118-
Baz::X(value) => value
119-
//[mir]~^ ERROR cannot use `senum.0` because it was mutably borrowed (Mir)
120-
};
121-
}
122-
// Static and field from union
123-
unsafe {
124-
let _ra = &mut sunion.a;
125-
sunion.a; //[mir]~ ERROR cannot use `sunion.a` because it was mutably borrowed (Mir)
126-
}
12793
// Deref and field from struct
12894
{
12995
let mut f = Box::new(Foo { x: 22 });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 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 taken from #45641 (https://github.com/rust-lang/rust/issues/45641)
12+
13+
// ignore-tidy-linelength
14+
// revisions: ast mir
15+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
16+
17+
static mut Y: u32 = 0;
18+
19+
unsafe fn should_ok() {
20+
Y = 1;
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2016 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+
// revisions: ast mir
12+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
13+
14+
// Test file taken from issue 45129 (https://github.com/rust-lang/rust/issues/45129)
15+
16+
struct Foo { x: [usize; 2] }
17+
18+
static mut SFOO: Foo = Foo { x: [23, 32] };
19+
20+
impl Foo {
21+
fn x(&mut self) -> &mut usize { &mut self.x[0] }
22+
}
23+
24+
fn main() {
25+
unsafe {
26+
let sfoo: *mut Foo = &mut SFOO;
27+
let x = (*sfoo).x();
28+
(*sfoo).x[1] += 1;
29+
*x += 1;
30+
}
31+
}

0 commit comments

Comments
 (0)