mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Add a non-shallow fake borrow
This commit is contained in:
parent
511bd78863
commit
50531806ee
@ -69,7 +69,8 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
|||||||
fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let kind = match self.kind {
|
let kind = match self.kind {
|
||||||
mir::BorrowKind::Shared => "",
|
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 ",
|
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
|
||||||
// FIXME: differentiate `TwoPhaseBorrow`
|
// FIXME: differentiate `TwoPhaseBorrow`
|
||||||
mir::BorrowKind::Mut {
|
mir::BorrowKind::Mut {
|
||||||
|
@ -17,9 +17,9 @@ use rustc_middle::hir::nested_filter::OnlyBodies;
|
|||||||
use rustc_middle::mir::tcx::PlaceTy;
|
use rustc_middle::mir::tcx::PlaceTy;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
||||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
|
FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
|
||||||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
|
||||||
VarBindingForm,
|
TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
|
self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
|
||||||
@ -1486,7 +1486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let first_borrow_desc;
|
let first_borrow_desc;
|
||||||
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
|
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 },
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
) => {
|
) => {
|
||||||
first_borrow_desc = "mutable ";
|
first_borrow_desc = "mutable ";
|
||||||
@ -1504,7 +1504,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
(
|
(
|
||||||
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
BorrowKind::Shared,
|
BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
|
||||||
) => {
|
) => {
|
||||||
first_borrow_desc = "immutable ";
|
first_borrow_desc = "immutable ";
|
||||||
let mut err = self.cannot_reborrow_already_borrowed(
|
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)
|
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) =
|
if let Some(immutable_section_description) =
|
||||||
self.classify_immutable_section(issued_borrow.assigned_place)
|
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 ";
|
first_borrow_desc = "first ";
|
||||||
self.cannot_reborrow_already_uniquely_borrowed(
|
self.cannot_reborrow_already_uniquely_borrowed(
|
||||||
span,
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3572,7 +3581,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let loan_span = loan_spans.args_or_use();
|
let loan_span = loan_spans.args_or_use();
|
||||||
|
|
||||||
let descr_place = self.describe_any_place(place.as_ref());
|
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) {
|
if let Some(section) = self.classify_immutable_section(loan.assigned_place) {
|
||||||
let mut err = self.cannot_mutate_in_immutable_section(
|
let mut err = self.cannot_mutate_in_immutable_section(
|
||||||
span,
|
span,
|
||||||
|
@ -654,7 +654,7 @@ impl UseSpans<'_> {
|
|||||||
match kind {
|
match kind {
|
||||||
Some(kd) => match kd {
|
Some(kd) => match kd {
|
||||||
rustc_middle::mir::BorrowKind::Shared
|
rustc_middle::mir::BorrowKind::Shared
|
||||||
| rustc_middle::mir::BorrowKind::Fake => {
|
| rustc_middle::mir::BorrowKind::Fake(_) => {
|
||||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,18 +1056,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(_), BorrowKind::Shared | BorrowKind::Fake)
|
(Read(_), BorrowKind::Shared | BorrowKind::Fake(_))
|
||||||
| (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
|
| (
|
||||||
Control::Continue
|
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
|
// This used to be a future compatibility warning (to be
|
||||||
// disallowed on NLL). See rust-lang/rust#56254
|
// disallowed on NLL). See rust-lang/rust#56254
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
(Write(WriteKind::Move), BorrowKind::Fake) => {
|
(Write(WriteKind::Move), BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
|
||||||
// Handled by initialization checks.
|
// Handled by initialization checks.
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
@ -1175,10 +1176,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
match rvalue {
|
match rvalue {
|
||||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||||
let access_kind = match bk {
|
let access_kind = match bk {
|
||||||
BorrowKind::Fake => {
|
BorrowKind::Fake(FakeBorrowKind::Shallow) => {
|
||||||
(Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
|
(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 { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
let wk = WriteKind::MutableBorrow(bk);
|
let wk = WriteKind::MutableBorrow(bk);
|
||||||
if allow_two_phase_borrow(bk) {
|
if allow_two_phase_borrow(bk) {
|
||||||
@ -1197,7 +1200,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
flow_state,
|
flow_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
let action = if bk == BorrowKind::Fake {
|
let action = if bk == BorrowKind::Fake(FakeBorrowKind::Shallow) {
|
||||||
InitializationRequiringAction::MatchOn
|
InitializationRequiringAction::MatchOn
|
||||||
} else {
|
} else {
|
||||||
InitializationRequiringAction::Borrow
|
InitializationRequiringAction::Borrow
|
||||||
@ -1556,7 +1559,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
|
|
||||||
// only mutable borrows should be 2-phase
|
// only mutable borrows should be 2-phase
|
||||||
assert!(match borrow.kind {
|
assert!(match borrow.kind {
|
||||||
BorrowKind::Shared | BorrowKind::Fake => false,
|
BorrowKind::Shared | BorrowKind::Fake(_) => false,
|
||||||
BorrowKind::Mut { .. } => true,
|
BorrowKind::Mut { .. } => true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2121,14 +2124,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
| WriteKind::Replace
|
| WriteKind::Replace
|
||||||
| WriteKind::StorageDeadOrDrop
|
| WriteKind::StorageDeadOrDrop
|
||||||
| WriteKind::MutableBorrow(BorrowKind::Shared)
|
| WriteKind::MutableBorrow(BorrowKind::Shared)
|
||||||
| WriteKind::MutableBorrow(BorrowKind::Fake),
|
| WriteKind::MutableBorrow(BorrowKind::Fake(_)),
|
||||||
)
|
)
|
||||||
| Write(
|
| Write(
|
||||||
WriteKind::Move
|
WriteKind::Move
|
||||||
| WriteKind::Replace
|
| WriteKind::Replace
|
||||||
| WriteKind::StorageDeadOrDrop
|
| WriteKind::StorageDeadOrDrop
|
||||||
| WriteKind::MutableBorrow(BorrowKind::Shared)
|
| 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()
|
if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err()
|
||||||
&& !self.has_buffered_diags()
|
&& !self.has_buffered_diags()
|
||||||
@ -2152,7 +2155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Read(
|
Read(
|
||||||
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake)
|
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_))
|
||||||
| ReadKind::Copy,
|
| ReadKind::Copy,
|
||||||
) => {
|
) => {
|
||||||
// Access authorized
|
// Access authorized
|
||||||
|
@ -55,7 +55,7 @@ use crate::Overlap;
|
|||||||
use crate::{AccessDepth, Deep, Shallow};
|
use crate::{AccessDepth, Deep, Shallow};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::{
|
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 rustc_middle::ty::{self, TyCtxt};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
@ -271,10 +271,10 @@ fn place_components_conflict<'tcx>(
|
|||||||
// If the second example, where we did, then we still know
|
// If the second example, where we did, then we still know
|
||||||
// that the borrow can access a *part* of our place that
|
// that the borrow can access a *part* of our place that
|
||||||
// our access cares about, so we still have a conflict.
|
// 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()
|
&& borrow_place.projection.len() < access_place.projection.len()
|
||||||
{
|
{
|
||||||
debug!("borrow_conflicts_with_place: fake borrow");
|
debug!("borrow_conflicts_with_place: shallow borrow");
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
|
debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use rustc_data_structures::graph::dominators::Dominators;
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
use rustc_middle::mir::visit::Visitor;
|
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::{BorrowKind, Mutability, Operand};
|
||||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||||
use rustc_middle::mir::{Statement, StatementKind};
|
use rustc_middle::mir::{Statement, StatementKind};
|
||||||
@ -239,10 +241,12 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||||||
match rvalue {
|
match rvalue {
|
||||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||||
let access_kind = match bk {
|
let access_kind = match bk {
|
||||||
BorrowKind::Fake => {
|
BorrowKind::Fake(FakeBorrowKind::Shallow) => {
|
||||||
(Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk)))
|
(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 { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
let wk = WriteKind::MutableBorrow(bk);
|
let wk = WriteKind::MutableBorrow(bk);
|
||||||
if allow_two_phase_borrow(bk) {
|
if allow_two_phase_borrow(bk) {
|
||||||
@ -357,8 +361,11 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||||||
// have already taken the reservation
|
// have already taken the reservation
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(_), BorrowKind::Fake | BorrowKind::Shared)
|
(Read(_), BorrowKind::Fake(_) | BorrowKind::Shared)
|
||||||
| (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => {
|
| (
|
||||||
|
Read(ReadKind::Borrow(BorrowKind::Fake(FakeBorrowKind::Shallow))),
|
||||||
|
BorrowKind::Mut { .. },
|
||||||
|
) => {
|
||||||
// Reads don't invalidate shared or shallow borrows
|
// 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
|
// only mutable borrows should be 2-phase
|
||||||
assert!(match borrow.kind {
|
assert!(match borrow.kind {
|
||||||
BorrowKind::Shared | BorrowKind::Fake => false,
|
BorrowKind::Shared | BorrowKind::Fake(_) => false,
|
||||||
BorrowKind::Mut { .. } => true,
|
BorrowKind::Mut { .. } => true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
BorrowKind::Shared => {
|
BorrowKind::Shared => {
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
|
||||||
}
|
}
|
||||||
BorrowKind::Fake => {
|
BorrowKind::Fake(_) => {
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow)
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow)
|
||||||
}
|
}
|
||||||
BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
@ -487,7 +487,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place)
|
Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place)
|
||||||
| Rvalue::AddressOf(Mutability::Not, place) => {
|
| Rvalue::AddressOf(Mutability::Not, place) => {
|
||||||
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
|
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
|
||||||
self.ccx,
|
self.ccx,
|
||||||
|
@ -105,7 +105,7 @@ where
|
|||||||
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
|
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
|
||||||
match kind {
|
match kind {
|
||||||
mir::BorrowKind::Mut { .. } => true,
|
mir::BorrowKind::Mut { .. } => true,
|
||||||
mir::BorrowKind::Shared | mir::BorrowKind::Fake => {
|
mir::BorrowKind::Shared | mir::BorrowKind::Fake(_) => {
|
||||||
self.shared_borrow_allows_mutation(place)
|
self.shared_borrow_allows_mutation(place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -924,7 +924,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Rvalue::Ref(_, BorrowKind::Fake, _) => {
|
Rvalue::Ref(_, BorrowKind::Fake(_), _) => {
|
||||||
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||||
self.fail(
|
self.fail(
|
||||||
location,
|
location,
|
||||||
|
@ -954,7 +954,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||||||
Ref(region, borrow_kind, ref place) => {
|
Ref(region, borrow_kind, ref place) => {
|
||||||
let kind_str = match borrow_kind {
|
let kind_str = match borrow_kind {
|
||||||
BorrowKind::Shared => "",
|
BorrowKind::Shared => "",
|
||||||
BorrowKind::Fake => "fake ",
|
BorrowKind::Fake(FakeBorrowKind::Deep) => "fake ",
|
||||||
|
BorrowKind::Fake(FakeBorrowKind::Shallow) => "fake shallow ",
|
||||||
BorrowKind::Mut { .. } => "mut ",
|
BorrowKind::Mut { .. } => "mut ",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||||||
impl BorrowKind {
|
impl BorrowKind {
|
||||||
pub fn mutability(&self) -> Mutability {
|
pub fn mutability(&self) -> Mutability {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowKind::Shared | BorrowKind::Fake => Mutability::Not,
|
BorrowKind::Shared | BorrowKind::Fake(_) => Mutability::Not,
|
||||||
BorrowKind::Mut { .. } => Mutability::Mut,
|
BorrowKind::Mut { .. } => Mutability::Mut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,7 +459,7 @@ impl BorrowKind {
|
|||||||
pub fn allows_two_phase_borrow(&self) -> bool {
|
pub fn allows_two_phase_borrow(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowKind::Shared
|
BorrowKind::Shared
|
||||||
| BorrowKind::Fake
|
| BorrowKind::Fake(_)
|
||||||
| BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => {
|
| BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -165,13 +165,16 @@ pub enum BorrowKind {
|
|||||||
/// Data must be immutable and is aliasable.
|
/// Data must be immutable and is aliasable.
|
||||||
Shared,
|
Shared,
|
||||||
|
|
||||||
/// The immediately borrowed place must be immutable, but projections from
|
/// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either
|
||||||
/// it don't need to be. For example, a shallow borrow of `a.b` doesn't
|
/// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]).
|
||||||
/// conflict with a mutable borrow of `a.b.c`.
|
|
||||||
///
|
///
|
||||||
/// This is used when lowering matches: when matching on a place we want to
|
/// This is used when lowering index expressions and matches. This is used to prevent code like
|
||||||
/// ensure that place have the same value from the start of the match until
|
/// the following from compiling:
|
||||||
/// an arm is selected. This prevents this code from compiling:
|
/// ```compile_fail,E0506
|
||||||
|
/// let mut x = vec![vec![0, 1]];
|
||||||
|
/// let y = vec![];
|
||||||
|
/// let _ = x[0][{x = y; 1}];
|
||||||
|
/// ```
|
||||||
/// ```compile_fail,E0510
|
/// ```compile_fail,E0510
|
||||||
/// let mut x = &Some(0);
|
/// let mut x = &Some(0);
|
||||||
/// match *x {
|
/// match *x {
|
||||||
@ -180,11 +183,8 @@ pub enum BorrowKind {
|
|||||||
/// Some(_) => (),
|
/// Some(_) => (),
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// This can't be a shared borrow because mutably borrowing (*x as Some).0
|
|
||||||
/// should not prevent `if let None = x { ... }`, for example, because the
|
|
||||||
/// mutating `(*x as Some).0` can't affect the discriminant of `x`.
|
|
||||||
/// We can also report errors with this kind of borrow differently.
|
/// We can also report errors with this kind of borrow differently.
|
||||||
Fake,
|
Fake(FakeBorrowKind),
|
||||||
|
|
||||||
/// Data is mutable and not aliasable.
|
/// Data is mutable and not aliasable.
|
||||||
Mut { kind: MutBorrowKind },
|
Mut { kind: MutBorrowKind },
|
||||||
@ -240,6 +240,57 @@ pub enum MutBorrowKind {
|
|||||||
ClosureCapture,
|
ClosureCapture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||||
|
#[derive(Hash, HashStable)]
|
||||||
|
pub enum FakeBorrowKind {
|
||||||
|
/// A shared shallow borrow. The immediately borrowed place must be immutable, but projections
|
||||||
|
/// from it don't need to be. For example, a shallow borrow of `a.b` doesn't conflict with a
|
||||||
|
/// mutable borrow of `a.b.c`.
|
||||||
|
///
|
||||||
|
/// This is used when lowering matches: when matching on a place we want to ensure that place
|
||||||
|
/// have the same value from the start of the match until an arm is selected. This prevents this
|
||||||
|
/// code from compiling:
|
||||||
|
/// ```compile_fail,E0510
|
||||||
|
/// let mut x = &Some(0);
|
||||||
|
/// match *x {
|
||||||
|
/// None => (),
|
||||||
|
/// Some(_) if { x = &None; false } => (),
|
||||||
|
/// Some(_) => (),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// This can't be a shared borrow because mutably borrowing `(*x as Some).0` should not checking
|
||||||
|
/// the discriminant or accessing other variants, because the mutating `(*x as Some).0` can't
|
||||||
|
/// affect the discriminant of `x`. E.g. the following is allowed:
|
||||||
|
/// ```rust
|
||||||
|
/// let mut x = Some(0);
|
||||||
|
/// match x {
|
||||||
|
/// Some(_)
|
||||||
|
/// if {
|
||||||
|
/// if let Some(ref mut y) = x {
|
||||||
|
/// *y += 1;
|
||||||
|
/// };
|
||||||
|
/// true
|
||||||
|
/// } => {}
|
||||||
|
/// _ => {}
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
Shallow,
|
||||||
|
/// A shared (deep) borrow. Data must be immutable and is aliasable.
|
||||||
|
///
|
||||||
|
/// This is used when lowering deref patterns, where shallow borrows wouldn't prevent something
|
||||||
|
/// like:
|
||||||
|
// ```compile_fail
|
||||||
|
// let mut b = Box::new(false);
|
||||||
|
// match b {
|
||||||
|
// deref!(true) => {} // not reached because `*b == false`
|
||||||
|
// _ if { *b = true; false } => {} // not reached because the guard is `false`
|
||||||
|
// deref!(false) => {} // not reached because the guard changed it
|
||||||
|
// // UB because we reached the unreachable.
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
Deep,
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ impl BorrowKind {
|
|||||||
|
|
||||||
// We have no type corresponding to a shallow borrow, so use
|
// We have no type corresponding to a shallow borrow, so use
|
||||||
// `&` as an approximation.
|
// `&` as an approximation.
|
||||||
BorrowKind::Fake => hir::Mutability::Not,
|
BorrowKind::Fake(_) => hir::Mutability::Not,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +653,7 @@ macro_rules! make_mir_visitor {
|
|||||||
BorrowKind::Shared => PlaceContext::NonMutatingUse(
|
BorrowKind::Shared => PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::SharedBorrow
|
NonMutatingUseContext::SharedBorrow
|
||||||
),
|
),
|
||||||
BorrowKind::Fake => PlaceContext::NonMutatingUse(
|
BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::FakeBorrow
|
NonMutatingUseContext::FakeBorrow
|
||||||
),
|
),
|
||||||
BorrowKind::Mut { .. } =>
|
BorrowKind::Mut { .. } =>
|
||||||
@ -1279,6 +1279,8 @@ pub enum NonMutatingUseContext {
|
|||||||
/// Shared borrow.
|
/// Shared borrow.
|
||||||
SharedBorrow,
|
SharedBorrow,
|
||||||
/// A fake borrow.
|
/// A fake borrow.
|
||||||
|
/// FIXME: do we need to distinguish shallow and deep fake borrows? In fact, do we need to
|
||||||
|
/// distinguish fake and normal deep borrows?
|
||||||
FakeBorrow,
|
FakeBorrow,
|
||||||
/// AddressOf for *const pointer.
|
/// AddressOf for *const pointer.
|
||||||
AddressOf,
|
AddressOf,
|
||||||
|
@ -685,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
fake_borrow_temp.into(),
|
fake_borrow_temp.into(),
|
||||||
Rvalue::Ref(
|
Rvalue::Ref(
|
||||||
tcx.lifetimes.re_erased,
|
tcx.lifetimes.re_erased,
|
||||||
BorrowKind::Fake,
|
BorrowKind::Fake(FakeBorrowKind::Shallow),
|
||||||
Place { local: base_place.local, projection },
|
Place { local: base_place.local, projection },
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -2106,7 +2106,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let re_erased = tcx.lifetimes.re_erased;
|
let re_erased = tcx.lifetimes.re_erased;
|
||||||
let scrutinee_source_info = self.source_info(scrutinee_span);
|
let scrutinee_source_info = self.source_info(scrutinee_span);
|
||||||
for &(place, temp) in fake_borrows {
|
for &(place, temp) in fake_borrows {
|
||||||
let borrow = Rvalue::Ref(re_erased, BorrowKind::Fake, place);
|
let borrow =
|
||||||
|
Rvalue::Ref(re_erased, BorrowKind::Fake(FakeBorrowKind::Shallow), place);
|
||||||
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
|
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
visit::walk_expr(&mut visitor, expr);
|
visit::walk_expr(&mut visitor, expr);
|
||||||
if visitor.found {
|
if visitor.found {
|
||||||
match borrow_kind {
|
match borrow_kind {
|
||||||
BorrowKind::Fake | BorrowKind::Shared
|
BorrowKind::Fake(_) | BorrowKind::Shared
|
||||||
if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
|
if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
|
||||||
{
|
{
|
||||||
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
|
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
|
||||||
@ -521,7 +521,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField)
|
self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField)
|
||||||
}
|
}
|
||||||
BorrowKind::Fake | BorrowKind::Shared => {}
|
BorrowKind::Fake(_) | BorrowKind::Shared => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Cast(..)
|
Rvalue::Cast(..)
|
||||||
| Rvalue::Ref(_, BorrowKind::Fake, _)
|
| Rvalue::Ref(_, BorrowKind::Fake(_), _)
|
||||||
| Rvalue::ShallowInitBox(..)
|
| Rvalue::ShallowInitBox(..)
|
||||||
| Rvalue::Use(..)
|
| Rvalue::Use(..)
|
||||||
| Rvalue::ThreadLocalRef(..)
|
| Rvalue::ThreadLocalRef(..)
|
||||||
|
@ -29,7 +29,7 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
|
|||||||
for statement in basic_block.statements.iter_mut() {
|
for statement in basic_block.statements.iter_mut() {
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::AscribeUserType(..)
|
StatementKind::AscribeUserType(..)
|
||||||
| StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _)))
|
| StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake(_), _)))
|
||||||
| StatementKind::Coverage(
|
| StatementKind::Coverage(
|
||||||
// These kinds of coverage statements are markers inserted during
|
// These kinds of coverage statements are markers inserted during
|
||||||
// MIR building, and are not needed after InstrumentCoverage.
|
// MIR building, and are not needed after InstrumentCoverage.
|
||||||
|
@ -384,7 +384,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||||||
match kind {
|
match kind {
|
||||||
// Reject these borrow types just to be safe.
|
// Reject these borrow types just to be safe.
|
||||||
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
|
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
|
||||||
BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
|
BorrowKind::Fake(_) | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
|
||||||
return Err(Unpromotable);
|
return Err(Unpromotable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind {
|
|||||||
use rustc_middle::mir::BorrowKind::*;
|
use rustc_middle::mir::BorrowKind::*;
|
||||||
match *self {
|
match *self {
|
||||||
Shared => stable_mir::mir::BorrowKind::Shared,
|
Shared => stable_mir::mir::BorrowKind::Shared,
|
||||||
Fake => stable_mir::mir::BorrowKind::Fake,
|
Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables)),
|
||||||
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
|
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,6 +247,17 @@ impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
|
||||||
|
type T = stable_mir::mir::FakeBorrowKind;
|
||||||
|
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||||
|
use rustc_middle::mir::FakeBorrowKind::*;
|
||||||
|
match *self {
|
||||||
|
Deep => stable_mir::mir::FakeBorrowKind::Deep,
|
||||||
|
Shallow => stable_mir::mir::FakeBorrowKind::Shallow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
||||||
type T = stable_mir::mir::NullOp;
|
type T = stable_mir::mir::NullOp;
|
||||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||||
|
@ -865,11 +865,9 @@ pub enum BorrowKind {
|
|||||||
/// Data must be immutable and is aliasable.
|
/// Data must be immutable and is aliasable.
|
||||||
Shared,
|
Shared,
|
||||||
|
|
||||||
/// The immediately borrowed place must be immutable, but projections from
|
/// An immutable, aliasable borrow that is discarded after borrow-checking. Can behave either
|
||||||
/// it don't need to be. This is used to prevent match guards from replacing
|
/// like a normal shared borrow or like a special shallow borrow (see [`FakeBorrowKind`]).
|
||||||
/// the scrutinee. For example, a fake borrow of `a.b` doesn't
|
Fake(FakeBorrowKind),
|
||||||
/// conflict with a mutable borrow of `a.b.c`.
|
|
||||||
Fake,
|
|
||||||
|
|
||||||
/// Data is mutable and not aliasable.
|
/// Data is mutable and not aliasable.
|
||||||
Mut {
|
Mut {
|
||||||
@ -884,7 +882,7 @@ impl BorrowKind {
|
|||||||
BorrowKind::Mut { .. } => Mutability::Mut,
|
BorrowKind::Mut { .. } => Mutability::Mut,
|
||||||
BorrowKind::Shared => Mutability::Not,
|
BorrowKind::Shared => Mutability::Not,
|
||||||
// FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation.
|
// FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation.
|
||||||
BorrowKind::Fake => Mutability::Not,
|
BorrowKind::Fake(_) => Mutability::Not,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,6 +894,17 @@ pub enum MutBorrowKind {
|
|||||||
ClosureCapture,
|
ClosureCapture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum FakeBorrowKind {
|
||||||
|
/// A shared (deep) borrow. Data must be immutable and is aliasable.
|
||||||
|
Deep,
|
||||||
|
/// The immediately borrowed place must be immutable, but projections from
|
||||||
|
/// it don't need to be. This is used to prevent match guards from replacing
|
||||||
|
/// the scrutinee. For example, a fake borrow of `a.b` doesn't
|
||||||
|
/// conflict with a mutable borrow of `a.b.c`.
|
||||||
|
Shallow,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Mutability {
|
pub enum Mutability {
|
||||||
Not,
|
Not,
|
||||||
|
@ -8,7 +8,7 @@ use std::{fmt, io, iter};
|
|||||||
|
|
||||||
use super::{AssertMessage, BinOp, TerminatorKind};
|
use super::{AssertMessage, BinOp, TerminatorKind};
|
||||||
|
|
||||||
use super::BorrowKind;
|
use super::{BorrowKind, FakeBorrowKind};
|
||||||
|
|
||||||
impl Display for Ty {
|
impl Display for Ty {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
@ -352,7 +352,8 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
|
|||||||
Rvalue::Ref(_, borrowkind, place) => {
|
Rvalue::Ref(_, borrowkind, place) => {
|
||||||
let kind = match borrowkind {
|
let kind = match borrowkind {
|
||||||
BorrowKind::Shared => "&",
|
BorrowKind::Shared => "&",
|
||||||
BorrowKind::Fake => "&fake ",
|
BorrowKind::Fake(FakeBorrowKind::Deep) => "&fake ",
|
||||||
|
BorrowKind::Fake(FakeBorrowKind::Shallow) => "&fake shallow ",
|
||||||
BorrowKind::Mut { .. } => "&mut ",
|
BorrowKind::Mut { .. } => "&mut ",
|
||||||
};
|
};
|
||||||
write!(writer, "{kind}{:?}", place)
|
write!(writer, "{kind}{:?}", place)
|
||||||
|
@ -60,7 +60,7 @@ fn full_tested_match() -> () {
|
|||||||
bb7: {
|
bb7: {
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = &((_2 as Some).0: i32);
|
_6 = &((_2 as Some).0: i32);
|
||||||
_3 = &fake _2;
|
_3 = &fake shallow _2;
|
||||||
StorageLive(_7);
|
StorageLive(_7);
|
||||||
_7 = guard() -> [return: bb8, unwind: bb16];
|
_7 = guard() -> [return: bb8, unwind: bb16];
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ fn full_tested_match2() -> () {
|
|||||||
bb7: {
|
bb7: {
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = &((_2 as Some).0: i32);
|
_6 = &((_2 as Some).0: i32);
|
||||||
_3 = &fake _2;
|
_3 = &fake shallow _2;
|
||||||
StorageLive(_7);
|
StorageLive(_7);
|
||||||
_7 = guard() -> [return: bb8, unwind: bb16];
|
_7 = guard() -> [return: bb8, unwind: bb16];
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ fn main() -> () {
|
|||||||
bb10: {
|
bb10: {
|
||||||
StorageLive(_7);
|
StorageLive(_7);
|
||||||
_7 = &((_2 as Some).0: i32);
|
_7 = &((_2 as Some).0: i32);
|
||||||
_3 = &fake _2;
|
_3 = &fake shallow _2;
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = guard() -> [return: bb11, unwind: bb24];
|
_8 = guard() -> [return: bb11, unwind: bb24];
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ fn main() -> () {
|
|||||||
bb16: {
|
bb16: {
|
||||||
StorageLive(_11);
|
StorageLive(_11);
|
||||||
_11 = &((_2 as Some).0: i32);
|
_11 = &((_2 as Some).0: i32);
|
||||||
_3 = &fake _2;
|
_3 = &fake shallow _2;
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
StorageLive(_13);
|
StorageLive(_13);
|
||||||
_13 = (*_11);
|
_13 = (*_11);
|
||||||
|
@ -72,8 +72,8 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb12: {
|
bb12: {
|
||||||
_6 = &fake (_3.0: &str);
|
_6 = &fake shallow (_3.0: &str);
|
||||||
_7 = &fake (_3.1: bool);
|
_7 = &fake shallow (_3.1: bool);
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_10 = const true;
|
_10 = const true;
|
||||||
switchInt(move _10) -> [0: bb14, otherwise: bb13];
|
switchInt(move _10) -> [0: bb14, otherwise: bb13];
|
||||||
|
@ -54,7 +54,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb9: {
|
bb9: {
|
||||||
_3 = &fake _1;
|
_3 = &fake shallow _1;
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = _2;
|
_8 = _2;
|
||||||
switchInt(move _8) -> [0: bb11, otherwise: bb10];
|
switchInt(move _8) -> [0: bb11, otherwise: bb10];
|
||||||
|
@ -80,8 +80,8 @@
|
|||||||
_6 = &(_2.1: bool);
|
_6 = &(_2.1: bool);
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = &(_2.2: std::string::String);
|
_8 = &(_2.2: std::string::String);
|
||||||
- _3 = &fake (_2.0: bool);
|
- _3 = &fake shallow (_2.0: bool);
|
||||||
- _4 = &fake (_2.1: bool);
|
- _4 = &fake shallow (_2.1: bool);
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_10 = _1;
|
_10 = _1;
|
||||||
@ -137,8 +137,8 @@
|
|||||||
_6 = &(_2.0: bool);
|
_6 = &(_2.0: bool);
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = &(_2.2: std::string::String);
|
_8 = &(_2.2: std::string::String);
|
||||||
- _3 = &fake (_2.0: bool);
|
- _3 = &fake shallow (_2.0: bool);
|
||||||
- _4 = &fake (_2.1: bool);
|
- _4 = &fake shallow (_2.1: bool);
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
StorageLive(_13);
|
StorageLive(_13);
|
||||||
_13 = _1;
|
_13 = _1;
|
||||||
|
@ -80,8 +80,8 @@
|
|||||||
_6 = &(_2.1: bool);
|
_6 = &(_2.1: bool);
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = &(_2.2: std::string::String);
|
_8 = &(_2.2: std::string::String);
|
||||||
- _3 = &fake (_2.0: bool);
|
- _3 = &fake shallow (_2.0: bool);
|
||||||
- _4 = &fake (_2.1: bool);
|
- _4 = &fake shallow (_2.1: bool);
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
_10 = _1;
|
_10 = _1;
|
||||||
@ -137,8 +137,8 @@
|
|||||||
_6 = &(_2.0: bool);
|
_6 = &(_2.0: bool);
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = &(_2.2: std::string::String);
|
_8 = &(_2.2: std::string::String);
|
||||||
- _3 = &fake (_2.0: bool);
|
- _3 = &fake shallow (_2.0: bool);
|
||||||
- _4 = &fake (_2.1: bool);
|
- _4 = &fake shallow (_2.1: bool);
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
StorageLive(_13);
|
StorageLive(_13);
|
||||||
_13 = _1;
|
_13 = _1;
|
||||||
|
@ -33,10 +33,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
- _3 = &fake _1;
|
- _3 = &fake shallow _1;
|
||||||
- _4 = &fake (*(*((_1 as Some).0: &&i32)));
|
- _4 = &fake shallow (*(*((_1 as Some).0: &&i32)));
|
||||||
- _5 = &fake (*((_1 as Some).0: &&i32));
|
- _5 = &fake shallow (*((_1 as Some).0: &&i32));
|
||||||
- _6 = &fake ((_1 as Some).0: &&i32);
|
- _6 = &fake shallow ((_1 as Some).0: &&i32);
|
||||||
+ nop;
|
+ nop;
|
||||||
+ nop;
|
+ nop;
|
||||||
+ nop;
|
+ nop;
|
||||||
|
@ -33,10 +33,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
- _3 = &fake _1;
|
- _3 = &fake shallow _1;
|
||||||
- _4 = &fake (*(*((_1 as Some).0: &&i32)));
|
- _4 = &fake shallow (*(*((_1 as Some).0: &&i32)));
|
||||||
- _5 = &fake (*((_1 as Some).0: &&i32));
|
- _5 = &fake shallow (*((_1 as Some).0: &&i32));
|
||||||
- _6 = &fake ((_1 as Some).0: &&i32);
|
- _6 = &fake shallow ((_1 as Some).0: &&i32);
|
||||||
+ nop;
|
+ nop;
|
||||||
+ nop;
|
+ nop;
|
||||||
+ nop;
|
+ nop;
|
||||||
|
Loading…
Reference in New Issue
Block a user