Do not registor borrows for unsafe lvalues
This commit is contained in:
parent
3be597acf3
commit
c9d1db7bc5
2 changed files with 50 additions and 42 deletions
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use rustc::mir::{self, Location, Mir};
|
use rustc::mir::{self, Location, Mir};
|
||||||
use rustc::mir::visit::Visitor;
|
use rustc::mir::visit::Visitor;
|
||||||
use rustc::ty::{Region, TyCtxt};
|
use rustc::ty::{self, Region, TyCtxt};
|
||||||
use rustc::ty::RegionKind;
|
use rustc::ty::RegionKind;
|
||||||
use rustc::ty::RegionKind::ReScope;
|
use rustc::ty::RegionKind::ReScope;
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||||
|
@ -71,10 +71,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
|
nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
|
||||||
-> Self {
|
-> Self {
|
||||||
let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
|
let mut visitor = GatherBorrows {
|
||||||
location_map: FxHashMap(),
|
tcx,
|
||||||
region_map: FxHashMap(),
|
mir,
|
||||||
region_span_map: FxHashMap()};
|
idx_vec: IndexVec::new(),
|
||||||
|
location_map: FxHashMap(),
|
||||||
|
region_map: FxHashMap(),
|
||||||
|
region_span_map: FxHashMap()
|
||||||
|
};
|
||||||
visitor.visit_mir(mir);
|
visitor.visit_mir(mir);
|
||||||
return Borrows { tcx: tcx,
|
return Borrows { tcx: tcx,
|
||||||
mir: mir,
|
mir: mir,
|
||||||
|
@ -84,17 +88,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
|
||||||
region_span_map: visitor.region_span_map,
|
region_span_map: visitor.region_span_map,
|
||||||
nonlexical_regioncx };
|
nonlexical_regioncx };
|
||||||
|
|
||||||
struct GatherBorrows<'tcx> {
|
struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||||
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
mir: &'a Mir<'tcx>,
|
||||||
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
|
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
|
||||||
location_map: FxHashMap<Location, BorrowIndex>,
|
location_map: FxHashMap<Location, BorrowIndex>,
|
||||||
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
|
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
|
||||||
region_span_map: FxHashMap<RegionKind, Span>,
|
region_span_map: FxHashMap<RegionKind, Span>,
|
||||||
}
|
}
|
||||||
impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
|
|
||||||
|
impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
|
||||||
fn visit_rvalue(&mut self,
|
fn visit_rvalue(&mut self,
|
||||||
rvalue: &mir::Rvalue<'tcx>,
|
rvalue: &mir::Rvalue<'tcx>,
|
||||||
location: mir::Location) {
|
location: mir::Location) {
|
||||||
if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
|
if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
|
||||||
|
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
|
||||||
|
|
||||||
let borrow = BorrowData {
|
let borrow = BorrowData {
|
||||||
location: location, kind: kind, region: region, lvalue: lvalue.clone(),
|
location: location, kind: kind, region: region, lvalue: lvalue.clone(),
|
||||||
};
|
};
|
||||||
|
@ -197,7 +206,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::StatementKind::Assign(_, ref rhs) => {
|
mir::StatementKind::Assign(_, ref rhs) => {
|
||||||
if let mir::Rvalue::Ref(region, _, _) = *rhs {
|
if let mir::Rvalue::Ref(region, _, ref lvalue) = *rhs {
|
||||||
|
if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
|
||||||
let index = self.location_map.get(&location).unwrap_or_else(|| {
|
let index = self.location_map.get(&location).unwrap_or_else(|| {
|
||||||
panic!("could not find BorrowIndex for location {:?}", location);
|
panic!("could not find BorrowIndex for location {:?}", location);
|
||||||
});
|
});
|
||||||
|
@ -248,3 +258,35 @@ impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
|
||||||
false // bottom = no Rvalue::Refs are active by default
|
false // bottom = no Rvalue::Refs are active by default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
|
||||||
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
mir: &'a Mir<'tcx>,
|
||||||
|
lvalue: &mir::Lvalue<'tcx>
|
||||||
|
) -> bool {
|
||||||
|
use self::mir::Lvalue::*;
|
||||||
|
use self::mir::ProjectionElem;
|
||||||
|
|
||||||
|
match *lvalue {
|
||||||
|
Local(_) => false,
|
||||||
|
Static(ref static_) => tcx.is_static_mut(static_.def_id),
|
||||||
|
Projection(ref proj) => {
|
||||||
|
match proj.elem {
|
||||||
|
ProjectionElem::Field(..) |
|
||||||
|
ProjectionElem::Downcast(..) |
|
||||||
|
ProjectionElem::Subslice { .. } |
|
||||||
|
ProjectionElem::ConstantIndex { .. } |
|
||||||
|
ProjectionElem::Index(_) => {
|
||||||
|
is_unsafe_lvalue(tcx, mir, &proj.base)
|
||||||
|
}
|
||||||
|
ProjectionElem::Deref => {
|
||||||
|
let ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||||
|
match ty.sty {
|
||||||
|
ty::TyRawPtr(..) => true,
|
||||||
|
_ => is_unsafe_lvalue(tcx, mir, &proj.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,12 +46,6 @@ impl Baz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut sfoo : Foo = Foo{x: 23 };
|
|
||||||
static mut sbar : Bar = Bar(23);
|
|
||||||
static mut stuple : (i32, i32) = (24, 25);
|
|
||||||
static mut senum : Baz = Baz::X(26);
|
|
||||||
static mut sunion : U = U { a: 0 };
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Local and field from struct
|
// Local and field from struct
|
||||||
{
|
{
|
||||||
|
@ -96,34 +90,6 @@ fn main() {
|
||||||
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
|
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
|
||||||
//[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
|
//[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
|
||||||
}
|
}
|
||||||
// Static and field from struct
|
|
||||||
unsafe {
|
|
||||||
let _x = sfoo.x();
|
|
||||||
sfoo.x; //[mir]~ ERROR cannot use `sfoo.x` because it was mutably borrowed (Mir)
|
|
||||||
}
|
|
||||||
// Static and field from tuple-struct
|
|
||||||
unsafe {
|
|
||||||
let _0 = sbar.x();
|
|
||||||
sbar.0; //[mir]~ ERROR cannot use `sbar.0` because it was mutably borrowed (Mir)
|
|
||||||
}
|
|
||||||
// Static and field from tuple
|
|
||||||
unsafe {
|
|
||||||
let _0 = &mut stuple.0;
|
|
||||||
stuple.0; //[mir]~ ERROR cannot use `stuple.0` because it was mutably borrowed (Mir)
|
|
||||||
}
|
|
||||||
// Static and field from enum
|
|
||||||
unsafe {
|
|
||||||
let _e0 = senum.x();
|
|
||||||
match senum {
|
|
||||||
Baz::X(value) => value
|
|
||||||
//[mir]~^ ERROR cannot use `senum.0` because it was mutably borrowed (Mir)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Static and field from union
|
|
||||||
unsafe {
|
|
||||||
let _ra = &mut sunion.a;
|
|
||||||
sunion.a; //[mir]~ ERROR cannot use `sunion.a` because it was mutably borrowed (Mir)
|
|
||||||
}
|
|
||||||
// Deref and field from struct
|
// Deref and field from struct
|
||||||
{
|
{
|
||||||
let mut f = Box::new(Foo { x: 22 });
|
let mut f = Box::new(Foo { x: 22 });
|
||||||
|
|
Loading…
Reference in a new issue