1
Fork 0

Add a non-shallow fake borrow

This commit is contained in:
Nadrieril 2024-04-07 00:30:28 +02:00
parent 511bd78863
commit 50531806ee
32 changed files with 188 additions and 92 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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 }
}

View file

@ -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

View file

@ -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");

View file

@ -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,
});