use rustc::mir::{self, Location, Mir};
use rustc::mir::visit::Visitor;
-use rustc::ty::{Region, TyCtxt};
+use rustc::ty::{self, Region, TyCtxt};
use rustc::ty::RegionKind;
use rustc::ty::RegionKind::ReScope;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
mir: &'a Mir<'tcx>,
nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
-> Self {
- let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
- location_map: FxHashMap(),
- region_map: FxHashMap(),
- region_span_map: FxHashMap()};
+ let mut visitor = GatherBorrows {
+ tcx,
+ mir,
+ idx_vec: IndexVec::new(),
+ location_map: FxHashMap(),
+ region_map: FxHashMap(),
+ region_span_map: FxHashMap()
+ };
visitor.visit_mir(mir);
return Borrows { tcx: tcx,
mir: mir,
region_span_map: visitor.region_span_map,
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>>,
location_map: FxHashMap<Location, BorrowIndex>,
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
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,
rvalue: &mir::Rvalue<'tcx>,
location: mir::Location) {
if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
+ if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
+
let borrow = BorrowData {
location: location, kind: kind, region: region, lvalue: lvalue.clone(),
};
}
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(|| {
panic!("could not find BorrowIndex for location {:?}", location);
});
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),
+ }
+ }
+ }
+ }
+ }
+}
}
}
-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() {
// Local and field from struct
{
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
//[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
{
let mut f = Box::new(Foo { x: 22 });