use crate::borrow_check::ArtificialField;
use crate::borrow_check::Overlap;
use crate::borrow_check::{AccessDepth, Deep, Shallow};
-use rustc::mir::{
- Body, BorrowKind, Place, PlaceBase, PlaceElem, PlaceRef, ProjectionElem, StaticKind,
-};
+use rustc::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
use rustc::ty::{self, TyCtxt};
use rustc_hir as hir;
use std::cmp::max;
/// dataflow).
crate fn places_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
borrow_place: &Place<'tcx>,
access_place: &Place<'tcx>,
) -> bool {
borrow_conflicts_with_place(
tcx,
- param_env,
body,
borrow_place,
BorrowKind::Mut { allow_two_phase_borrow: true },
/// order to make the conservative choice and preserve soundness.
pub(super) fn borrow_conflicts_with_place<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
borrow_place: &Place<'tcx>,
borrow_kind: BorrowKind,
}
}
- place_components_conflict(
- tcx,
- param_env,
- body,
- borrow_place,
- borrow_kind,
- access_place,
- access,
- bias,
- )
+ place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias)
}
fn place_components_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
borrow_place: &Place<'tcx>,
borrow_kind: BorrowKind,
// and either equal or disjoint.
// - If we did run out of access, the borrow can access a part of it.
- let borrow_base = &borrow_place.base;
- let access_base = access_place.base;
+ let borrow_local = borrow_place.local;
+ let access_local = access_place.local;
- match place_base_conflict(tcx, param_env, borrow_base, access_base) {
+ match place_base_conflict(borrow_local, access_local) {
Overlap::Arbitrary => {
bug!("Two base can't return Arbitrary");
}
match place_projection_conflict(
tcx,
body,
- borrow_base,
+ borrow_local,
borrow_proj_base,
borrow_c,
access_c,
// access cares about.
let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
- let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty;
+ let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
match (elem, &base_ty.kind, access) {
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
// Given that the bases of `elem1` and `elem2` are always either equal
// or disjoint (and have the same type!), return the overlap situation
// between `elem1` and `elem2`.
-fn place_base_conflict<'tcx>(
- tcx: TyCtxt<'tcx>,
- _param_env: ty::ParamEnv<'tcx>,
- elem1: &PlaceBase<'tcx>,
- elem2: &PlaceBase<'tcx>,
-) -> Overlap {
- match (elem1, elem2) {
- (PlaceBase::Local(l1), PlaceBase::Local(l2)) => {
- if l1 == l2 {
- // the same local - base case, equal
- debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
- Overlap::EqualOrDisjoint
- } else {
- // different locals - base case, disjoint
- debug!("place_element_conflict: DISJOINT-LOCAL");
- Overlap::Disjoint
- }
- }
- (PlaceBase::Static(s1), PlaceBase::Static(s2)) => {
- match (&s1.kind, &s2.kind) {
- (StaticKind::Static, StaticKind::Static) => {
- if s1.def_id != s2.def_id {
- debug!("place_element_conflict: DISJOINT-STATIC");
- Overlap::Disjoint
- } else if tcx.is_mutable_static(s1.def_id) {
- // We ignore mutable statics - they can only be unsafe code.
- debug!("place_element_conflict: IGNORE-STATIC-MUT");
- Overlap::Disjoint
- } else {
- debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
- Overlap::EqualOrDisjoint
- }
- }
- }
- }
- (PlaceBase::Local(_), PlaceBase::Static(_))
- | (PlaceBase::Static(_), PlaceBase::Local(_)) => {
- debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
- Overlap::Disjoint
- }
+fn place_base_conflict(l1: Local, l2: Local) -> Overlap {
+ if l1 == l2 {
+ // the same local - base case, equal
+ debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
+ Overlap::EqualOrDisjoint
+ } else {
+ // different locals - base case, disjoint
+ debug!("place_element_conflict: DISJOINT-LOCAL");
+ Overlap::Disjoint
}
}
fn place_projection_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- pi1_base: &PlaceBase<'tcx>,
+ pi1_local: Local,
pi1_proj_base: &[PlaceElem<'tcx>],
pi1_elem: &PlaceElem<'tcx>,
pi2_elem: &PlaceElem<'tcx>,
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
Overlap::EqualOrDisjoint
} else {
- let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty;
+ let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
match ty.kind {
ty::Adt(def, _) if def.is_union() => {
// Different fields of a union, we are basically stuck.