Add a non-shallow fake borrow
This commit is contained in:
parent
511bd78863
commit
50531806ee
32 changed files with 188 additions and 92 deletions
|
@ -69,7 +69,8 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
|||
fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let kind = match self.kind {
|
||||
mir::BorrowKind::Shared => "",
|
||||
mir::BorrowKind::Fake => "fake ",
|
||||
mir::BorrowKind::Fake(mir::FakeBorrowKind::Deep) => "fake ",
|
||||
mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow) => "fake shallow ",
|
||||
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
|
||||
// FIXME: differentiate `TwoPhaseBorrow`
|
||||
mir::BorrowKind::Mut {
|
||||
|
|
|
@ -17,9 +17,9 @@ use rustc_middle::hir::nested_filter::OnlyBodies;
|
|||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
|
||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
VarBindingForm,
|
||||
FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
|
||||
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
|
||||
TerminatorKind, VarBindingForm,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
|
||||
|
@ -1486,7 +1486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let first_borrow_desc;
|
||||
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
|
||||
(
|
||||
BorrowKind::Shared,
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
) => {
|
||||
first_borrow_desc = "mutable ";
|
||||
|
@ -1504,7 +1504,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
(
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||
BorrowKind::Shared,
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
|
||||
) => {
|
||||
first_borrow_desc = "immutable ";
|
||||
let mut err = self.cannot_reborrow_already_borrowed(
|
||||
|
@ -1566,7 +1566,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
|
||||
}
|
||||
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Fake) => {
|
||||
(BorrowKind::Mut { .. }, BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
|
||||
if let Some(immutable_section_description) =
|
||||
self.classify_immutable_section(issued_borrow.assigned_place)
|
||||
{
|
||||
|
@ -1629,7 +1629,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
(BorrowKind::Shared, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
|
||||
(
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
|
||||
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||
) => {
|
||||
first_borrow_desc = "first ";
|
||||
self.cannot_reborrow_already_uniquely_borrowed(
|
||||
span,
|
||||
|
@ -1659,8 +1662,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Fake)
|
||||
| (BorrowKind::Fake, BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) => {
|
||||
(
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
|
||||
BorrowKind::Shared | BorrowKind::Fake(_),
|
||||
)
|
||||
| (
|
||||
BorrowKind::Fake(FakeBorrowKind::Shallow),
|
||||
BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_),
|
||||
) => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
@ -3572,7 +3581,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let loan_span = loan_spans.args_or_use();
|
||||
|
||||
let descr_place = self.describe_any_place(place.as_ref());
|
||||
if loan.kind == BorrowKind::Fake {
|
||||
if let BorrowKind::Fake(_) = loan.kind {
|
||||
if let Some(section) = self.classify_immutable_section(loan.assigned_place) {
|
||||
let mut err = self.cannot_mutate_in_immutable_section(
|
||||
span,
|
||||
|
|
|
@ -654,7 +654,7 @@ impl UseSpans<'_> {
|
|||
match kind {
|
||||
Some(kd) => match kd {
|
||||
rustc_middle::mir::BorrowKind::Shared
|
||||
| rustc_middle::mir::BorrowKind::Fake => {
|
||||
| rustc_middle::mir::BorrowKind::Fake(_) => {
|
||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
||||
}
|
||||
|
||||
|
|
|
@ -1056,18 +1056,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
Control::Continue
|
||||
}
|
||||
|
||||
(Read(_), BorrowKind::Shared | BorrowKind::Fake)
|
||||
| (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
|
||||
Control::Continue
|
||||
}
|
||||
(Read(_), BorrowKind::Shared | BorrowKind::Fake(_))
|
||||
| (
|
||||
Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))),
|
||||
BorrowKind::Mut { .. },
|
||||
) => Control::Continue,
|
||||
|
||||
(Reservation(_), BorrowKind::Fake | BorrowKind::Shared) => {
|
||||
(Reservation(_), BorrowKind::Fake(_) | BorrowKind::Shared) => {
|
||||
// This used to be a future compatibility warning (to be
|
||||
// disallowed on NLL). See rust-lang/rust#56254
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
(Write(WriteKind::Move), BorrowKind::Fake) => {
|
||||
(Write(WriteKind::Move), BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
|
||||
// Handled by initialization checks.
|
||||
Control::Continue
|
||||
}
|
||||
|
@ -1175,10 +1176,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
let access_kind = match bk {
|
||||
BorrowKind::Fake => {
|
||||
BorrowKind::Fake(FakeBorrowKind::Shallow) => {
|
||||
(Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep) => {
|
||||
(Deep, Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if allow_two_phase_borrow(bk) {
|
||||
|
@ -1197,7 +1200,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
flow_state,
|
||||
);
|
||||
|
||||
let action = if bk == BorrowKind::Fake {
|
||||
let action = if bk == BorrowKind::Fake(FakeBorrowKind::Shallow) {
|
||||
InitializationRequiringAction::MatchOn
|
||||
} else {
|
||||
InitializationRequiringAction::Borrow
|
||||
|
@ -1556,7 +1559,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
// only mutable borrows should be 2-phase
|
||||
assert!(match borrow.kind {
|
||||
BorrowKind::Shared | BorrowKind::Fake => false,
|
||||
BorrowKind::Shared | BorrowKind::Fake(_) => false,
|
||||
BorrowKind::Mut { .. } => true,
|
||||
});
|
||||
|
||||
|
@ -2121,14 +2124,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
| WriteKind::Replace
|
||||
| WriteKind::StorageDeadOrDrop
|
||||
| WriteKind::MutableBorrow(BorrowKind::Shared)
|
||||
| WriteKind::MutableBorrow(BorrowKind::Fake),
|
||||
| WriteKind::MutableBorrow(BorrowKind::Fake(_)),
|
||||
)
|
||||
| Write(
|
||||
WriteKind::Move
|
||||
| WriteKind::Replace
|
||||
| WriteKind::StorageDeadOrDrop
|
||||
| WriteKind::MutableBorrow(BorrowKind::Shared)
|
||||
| WriteKind::MutableBorrow(BorrowKind::Fake),
|
||||
| WriteKind::MutableBorrow(BorrowKind::Fake(_)),
|
||||
) => {
|
||||
if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err()
|
||||
&& !self.has_buffered_diags()
|
||||
|
@ -2152,7 +2155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
Read(
|
||||
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake)
|
||||
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_))
|
||||
| ReadKind::Copy,
|
||||
) => {
|
||||
// Access authorized
|
||||
|
|
|
@ -55,7 +55,7 @@ use crate::Overlap;
|
|||
use crate::{AccessDepth, Deep, Shallow};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir::{
|
||||
Body, BorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
|
||||
Body, BorrowKind, FakeBorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
|
||||
};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use std::cmp::max;
|
||||
|
@ -271,10 +271,10 @@ fn place_components_conflict<'tcx>(
|
|||
// If the second example, where we did, then we still know
|
||||
// that the borrow can access a *part* of our place that
|
||||
// our access cares about, so we still have a conflict.
|
||||
if borrow_kind == BorrowKind::Fake
|
||||
if borrow_kind == BorrowKind::Fake(FakeBorrowKind::Shallow)
|
||||
&& borrow_place.projection.len() < access_place.projection.len()
|
||||
{
|
||||
debug!("borrow_conflicts_with_place: fake borrow");
|
||||
debug!("borrow_conflicts_with_place: shallow borrow");
|
||||
false
|
||||
} else {
|
||||
debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue};
|
||||
use rustc_middle::mir::{
|
||||
self, BasicBlock, Body, FakeBorrowKind, Location, NonDivergingIntrinsic, Place, Rvalue,
|
||||
};
|
||||
use rustc_middle::mir::{BorrowKind, Mutability, Operand};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::mir::{Statement, StatementKind};
|
||||
|
@ -239,10 +241,12 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
let access_kind = match bk {
|
||||
BorrowKind::Fake => {
|
||||
BorrowKind::Fake(FakeBorrowKind::Shallow) => {
|
||||
(Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep) => {
|
||||
(Deep, Read(ReadKind::Borrow(bk)))
|
||||
}
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if allow_two_phase_borrow(bk) {
|
||||
|
@ -357,8 +361,11 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||
// have already taken the reservation
|
||||
}
|
||||
|
||||
(Read(_), BorrowKind::Fake | BorrowKind::Shared)
|
||||
| (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
|
||||
(Read(_), BorrowKind::Fake(_) | BorrowKind::Shared)
|
||||
| (
|
||||
Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))),
|
||||
BorrowKind::Mut { .. },
|
||||
) => {
|
||||
// Reads don't invalidate shared or shallow borrows
|
||||
}
|
||||
|
||||
|
@ -403,7 +410,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||
|
||||
// only mutable borrows should be 2-phase
|
||||
assert!(match borrow.kind {
|
||||
BorrowKind::Shared | BorrowKind::Fake => false,
|
||||
BorrowKind::Shared | BorrowKind::Fake(_) => false,
|
||||
BorrowKind::Mut { .. } => true,
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue