1
Fork 0

merge BorrowKind::Unique into BorrowKind::Mut

This commit is contained in:
Ziru Niu 2023-05-31 06:25:27 +08:00
parent 6fc0273b5a
commit 8fb4c41f35
21 changed files with 109 additions and 105 deletions

View file

@ -72,7 +72,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
let kind = match self.kind { let kind = match self.kind {
mir::BorrowKind::Shared => "", mir::BorrowKind::Shared => "",
mir::BorrowKind::Shallow => "shallow ", mir::BorrowKind::Shallow => "shallow ",
mir::BorrowKind::Unique => "uniq ", mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
mir::BorrowKind::Mut { .. } => "mut ", mir::BorrowKind::Mut { .. } => "mut ",
}; };
write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place) write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)

View file

@ -15,8 +15,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, Operand, Place, PlaceRef, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
VarBindingForm,
}; };
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty}; use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_middle::util::CallKind; use rustc_middle::util::CallKind;
@ -926,7 +927,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// FIXME: supply non-"" `opt_via` when appropriate // FIXME: supply non-"" `opt_via` when appropriate
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::Mut { .. }) => { (
BorrowKind::Shared,
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
) => {
first_borrow_desc = "mutable "; first_borrow_desc = "mutable ";
self.cannot_reborrow_already_borrowed( self.cannot_reborrow_already_borrowed(
span, span,
@ -940,7 +944,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None, None,
) )
} }
(BorrowKind::Mut { .. }, BorrowKind::Shared) => { (
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
BorrowKind::Shared,
) => {
first_borrow_desc = "immutable "; first_borrow_desc = "immutable ";
let mut err = self.cannot_reborrow_already_borrowed( let mut err = self.cannot_reborrow_already_borrowed(
span, span,
@ -962,7 +969,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err err
} }
(BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => { (
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
) => {
first_borrow_desc = "first "; first_borrow_desc = "first ";
let mut err = self.cannot_mutably_borrow_multiply( let mut err = self.cannot_mutably_borrow_multiply(
span, span,
@ -985,12 +995,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err err
} }
(BorrowKind::Unique, BorrowKind::Unique) => { (
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
) => {
first_borrow_desc = "first "; first_borrow_desc = "first ";
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::Unique, BorrowKind::Shallow) => { (BorrowKind::Mut { .. }, BorrowKind::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)
{ {
@ -1004,7 +1017,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_spans.var_subdiag( borrow_spans.var_subdiag(
None, None,
&mut err, &mut err,
Some(BorrowKind::Unique), Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|kind, var_span| { |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*; use crate::session_diagnostics::CaptureVarCause::*;
match kind { match kind {
@ -1038,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} }
(BorrowKind::Unique, _) => { (BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }, _) => {
first_borrow_desc = "first "; first_borrow_desc = "first ";
self.cannot_uniquely_borrow_by_one_closure( self.cannot_uniquely_borrow_by_one_closure(
span, span,
@ -1052,7 +1065,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) )
} }
(BorrowKind::Shared, BorrowKind::Unique) => { (BorrowKind::Shared, 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,
@ -1067,7 +1080,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) )
} }
(BorrowKind::Mut { .. }, BorrowKind::Unique) => { (BorrowKind::Mut { .. }, 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,
@ -1085,10 +1098,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow) (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow)
| ( | (
BorrowKind::Shallow, BorrowKind::Shallow,
BorrowKind::Mut { .. } BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow,
| BorrowKind::Unique
| BorrowKind::Shared
| BorrowKind::Shallow,
) => unreachable!(), ) => unreachable!(),
}; };

View file

@ -629,9 +629,9 @@ impl UseSpans<'_> {
Some(kd) => match kd { Some(kd) => match kd {
rustc_middle::mir::BorrowKind::Shared rustc_middle::mir::BorrowKind::Shared
| rustc_middle::mir::BorrowKind::Shallow | rustc_middle::mir::BorrowKind::Shallow
| rustc_middle::mir::BorrowKind::Unique => { | rustc_middle::mir::BorrowKind::Mut {
CaptureVarKind::Immut { kind_span: capture_kind_span } kind: rustc_middle::mir::MutBorrowKind::ClosureCapture,
} } => CaptureVarKind::Immut { kind_span: capture_kind_span },
rustc_middle::mir::BorrowKind::Mut { .. } => { rustc_middle::mir::BorrowKind::Mut { .. } => {
CaptureVarKind::Mut { kind_span: capture_kind_span } CaptureVarKind::Mut { kind_span: capture_kind_span }

View file

@ -234,7 +234,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
borrow_spans.var_subdiag( borrow_spans.var_subdiag(
None, None,
&mut err, &mut err,
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }), Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|_kind, var_span| { |_kind, var_span| {
let place = self.describe_any_place(access_place.as_ref()); let place = self.describe_any_place(access_place.as_ref());
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
_, _,
mir::Rvalue::Ref( mir::Rvalue::Ref(
_, _,
mir::BorrowKind::Mut { allow_two_phase_borrow: false }, mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
_, _,
), ),
)), )),

View file

@ -255,7 +255,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
} }
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
BorrowKind::Unique | 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) {
(Deep, Reservation(wk)) (Deep, Reservation(wk))
@ -273,7 +273,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
Mutability::Mut => ( Mutability::Mut => (
Deep, Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut { Write(WriteKind::MutableBorrow(BorrowKind::Mut {
allow_two_phase_borrow: false, kind: mir::MutBorrowKind::Default,
})), })),
), ),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
@ -376,14 +376,11 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
} }
(Read(_), BorrowKind::Shallow | BorrowKind::Shared) (Read(_), BorrowKind::Shallow | BorrowKind::Shared)
| ( | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
Read(ReadKind::Borrow(BorrowKind::Shallow)),
BorrowKind::Unique | BorrowKind::Mut { .. },
) => {
// Reads don't invalidate shared or shallow borrows // Reads don't invalidate shared or shallow borrows
} }
(Read(_), BorrowKind::Unique | BorrowKind::Mut { .. }) => { (Read(_), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK. // Reading from mere reservations of mutable-borrows is OK.
if !is_active(&this.dominators, borrow, location) { if !is_active(&this.dominators, borrow, location) {
// If the borrow isn't active yet, reads don't invalidate it // If the borrow isn't active yet, reads don't invalidate it
@ -425,7 +422,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'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::Shallow => false, BorrowKind::Shared | BorrowKind::Shallow => false,
BorrowKind::Unique | BorrowKind::Mut { .. } => true, BorrowKind::Mut { .. } => true,
}); });
self.access_place( self.access_place(

View file

@ -29,8 +29,8 @@ use rustc_infer::infer::{
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
}; };
use rustc_middle::mir::{ use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, traversal, Body, ClearCrossCrate, Local, Location, MutBorrowKind, Mutability,
Place, PlaceElem, PlaceRef, VarDebugInfoContents, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents,
}; };
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
@ -1071,10 +1071,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
(Read(_), BorrowKind::Shared | BorrowKind::Shallow) (Read(_), BorrowKind::Shared | BorrowKind::Shallow)
| ( | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
Read(ReadKind::Borrow(BorrowKind::Shallow)), Control::Continue
BorrowKind::Unique | BorrowKind::Mut { .. }, }
) => Control::Continue,
(Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => { (Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => {
// This used to be a future compatibility warning (to be // This used to be a future compatibility warning (to be
@ -1087,7 +1086,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Control::Continue Control::Continue
} }
(Read(kind), BorrowKind::Unique | BorrowKind::Mut { .. }) => { (Read(kind), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK. // Reading from mere reservations of mutable-borrows is OK.
if !is_active(this.dominators(), borrow, location) { if !is_active(this.dominators(), borrow, location) {
assert!(allow_two_phase_borrow(borrow.kind)); assert!(allow_two_phase_borrow(borrow.kind));
@ -1194,7 +1193,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
} }
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
BorrowKind::Unique | 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) {
(Deep, Reservation(wk)) (Deep, Reservation(wk))
@ -1231,7 +1230,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Mutability::Mut => ( Mutability::Mut => (
Deep, Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut { Write(WriteKind::MutableBorrow(BorrowKind::Mut {
allow_two_phase_borrow: false, kind: MutBorrowKind::Default,
})), })),
), ),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
@ -1565,7 +1564,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::Shallow => false, BorrowKind::Shared | BorrowKind::Shallow => false,
BorrowKind::Unique | BorrowKind::Mut { .. } => true, BorrowKind::Mut { .. } => true,
}); });
self.access_place( self.access_place(
@ -1959,14 +1958,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let the_place_err; let the_place_err;
match kind { match kind {
Reservation(WriteKind::MutableBorrow( Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }), | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) => {
))
| Write(WriteKind::MutableBorrow(
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
)) => {
let is_local_mutation_allowed = match borrow_kind { let is_local_mutation_allowed = match borrow_kind {
BorrowKind::Unique => LocalMutationIsAllowed::Yes, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
LocalMutationIsAllowed::Yes
}
BorrowKind::Mut { .. } => is_local_mutation_allowed, BorrowKind::Mut { .. } => is_local_mutation_allowed,
BorrowKind::Shared | BorrowKind::Shallow => unreachable!(), BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
}; };
@ -2031,12 +2028,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return false; return false;
} }
Read( Read(
ReadKind::Borrow( ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow)
BorrowKind::Unique
| BorrowKind::Mut { .. }
| BorrowKind::Shared
| BorrowKind::Shallow,
)
| ReadKind::Copy, | ReadKind::Copy,
) => { ) => {
// Access authorized // Access authorized

View file

@ -4,7 +4,9 @@ use crate::ArtificialField;
use crate::Overlap; 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::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem}; use rustc_middle::mir::{
Body, BorrowKind, Local, 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;
use std::iter; use std::iter;
@ -35,7 +37,7 @@ pub fn places_conflict<'tcx>(
tcx, tcx,
body, body,
borrow_place, borrow_place,
BorrowKind::Mut { allow_two_phase_borrow: true }, BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow },
access_place.as_ref(), access_place.as_ref(),
AccessDepth::Deep, AccessDepth::Deep,
bias, bias,

View file

@ -412,7 +412,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
BorrowKind::Shallow => { BorrowKind::Shallow => {
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
} }
BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
BorrowKind::Mut { .. } => { BorrowKind::Mut { .. } => {
PlaceContext::MutatingUse(MutatingUseContext::Borrow) PlaceContext::MutatingUse(MutatingUseContext::Borrow)
} }
@ -457,7 +456,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} }
} }
Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique), place) => { Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, place) => {
let ty = place.ty(self.body, self.tcx).ty; let ty = place.ty(self.body, self.tcx).ty;
let is_allowed = match ty.kind() { let is_allowed = match ty.kind() {
// Inside a `static mut`, `&mut [...]` is allowed. // Inside a `static mut`, `&mut [...]` is allowed.

View file

@ -103,7 +103,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::Shallow | mir::BorrowKind::Unique => { mir::BorrowKind::Shared | mir::BorrowKind::Shallow => {
self.shared_borrow_allows_mutation(place) self.shared_borrow_allows_mutation(place)
} }
} }

View file

@ -454,7 +454,9 @@ 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::Shallow | BorrowKind::Unique => return Err(Unpromotable), BorrowKind::Shallow | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
return Err(Unpromotable);
}
BorrowKind::Shared => { BorrowKind::Shared => {
let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local); let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);

View file

@ -2035,22 +2035,24 @@ 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::Shallow | BorrowKind::Unique => Mutability::Not, BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not,
BorrowKind::Mut { .. } => Mutability::Mut, BorrowKind::Mut { .. } => Mutability::Mut,
} }
} }
pub fn allows_two_phase_borrow(&self) -> bool { pub fn allows_two_phase_borrow(&self) -> bool {
match *self { match *self {
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, BorrowKind::Shared | BorrowKind::Shallow => false,
BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, BorrowKind::Mut { kind } => kind == MutBorrowKind::TwoPhaseBorrow,
} }
} }
// FIXME: won't be used after diagnostic migration // FIXME: won't be used after diagnostic migration
pub fn describe_mutability(&self) -> &str { pub fn describe_mutability(&self) -> &str {
match *self { match *self {
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable", BorrowKind::Shared
| BorrowKind::Shallow
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => "immutable",
BorrowKind::Mut { .. } => "mutable", BorrowKind::Mut { .. } => "mutable",
} }
} }
@ -2090,7 +2092,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let kind_str = match borrow_kind { let kind_str = match borrow_kind {
BorrowKind::Shared => "", BorrowKind::Shared => "",
BorrowKind::Shallow => "shallow ", BorrowKind::Shallow => "shallow ",
BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ", BorrowKind::Mut { .. } => "mut ",
}; };
// When printing regions, add trailing space if necessary. // When printing regions, add trailing space if necessary.

View file

@ -182,6 +182,16 @@ pub enum BorrowKind {
/// We can also report errors with this kind of borrow differently. /// We can also report errors with this kind of borrow differently.
Shallow, Shallow,
/// Data is mutable and not aliasable.
Mut { kind: MutBorrowKind },
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)]
pub enum MutBorrowKind {
Default,
/// this borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`)
TwoPhaseBorrow,
/// Data must be immutable but not aliasable. This kind of borrow /// Data must be immutable but not aliasable. This kind of borrow
/// cannot currently be expressed by the user and is used only in /// cannot currently be expressed by the user and is used only in
/// implicit closure bindings. It is needed when the closure is /// implicit closure bindings. It is needed when the closure is
@ -220,19 +230,7 @@ pub enum BorrowKind {
/// immutable, but not aliasable. This solves the problem. For /// immutable, but not aliasable. This solves the problem. For
/// simplicity, we don't give users the way to express this /// simplicity, we don't give users the way to express this
/// borrow, it's just used when translating closures. /// borrow, it's just used when translating closures.
/// ClosureCapture,
// FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
// that they do not require their pointee to be marked as a mutable.
// They should still be treated as mutable borrows in every other way,
// e.g. for variance or overlap checking.
Unique,
/// Data is mutable and not aliasable.
Mut {
/// `true` if this borrow arose from method-call auto-ref
/// (i.e., `adjustment::Adjust::Borrow`).
allow_two_phase_borrow: bool,
},
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View file

@ -269,11 +269,6 @@ impl BorrowKind {
BorrowKind::Mut { .. } => hir::Mutability::Mut, BorrowKind::Mut { .. } => hir::Mutability::Mut,
BorrowKind::Shared => hir::Mutability::Not, BorrowKind::Shared => hir::Mutability::Not,
// We have no type corresponding to a unique imm borrow, so
// use `&mut`. It gives all the capabilities of a `&uniq`
// and hence is a safe "over approximation".
BorrowKind::Unique => hir::Mutability::Mut,
// 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::Shallow => hir::Mutability::Not, BorrowKind::Shallow => hir::Mutability::Not,

View file

@ -650,9 +650,6 @@ macro_rules! make_mir_visitor {
BorrowKind::Shallow => PlaceContext::NonMutatingUse( BorrowKind::Shallow => PlaceContext::NonMutatingUse(
NonMutatingUseContext::ShallowBorrow NonMutatingUseContext::ShallowBorrow
), ),
BorrowKind::Unique => PlaceContext::MutatingUse(
MutatingUseContext::Borrow
),
BorrowKind::Mut { .. } => BorrowKind::Mut { .. } =>
PlaceContext::MutatingUse(MutatingUseContext::Borrow), PlaceContext::MutatingUse(MutatingUseContext::Borrow),
}; };

View file

@ -442,7 +442,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
match upvar.kind { match upvar.kind {
ExprKind::Borrow { ExprKind::Borrow {
borrow_kind: borrow_kind:
BorrowKind::Mut { allow_two_phase_borrow: false }, BorrowKind::Mut { kind: MutBorrowKind::Default },
arg, arg,
} => unpack!( } => unpack!(
block = this.limit_capture_mutability( block = this.limit_capture_mutability(
@ -795,8 +795,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}; };
let borrow_kind = match mutability { let borrow_kind = match mutability {
Mutability::Not => BorrowKind::Unique, Mutability::Not => BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
}; };
let arg_place = arg_place_builder.to_place(this); let arg_place = arg_place_builder.to_place(this);

View file

@ -3,7 +3,7 @@ use crate::errors::*;
use rustc_middle::thir::visit::{self, Visitor}; use rustc_middle::thir::visit::{self, Visitor};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::mir::BorrowKind; use rustc_middle::mir::{BorrowKind, MutBorrowKind};
use rustc_middle::thir::*; use rustc_middle::thir::*;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
@ -254,7 +254,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
); );
}; };
match borrow_kind { match borrow_kind {
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { BorrowKind::Shallow
| BorrowKind::Shared
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
if !ty.is_freeze(self.tcx, self.param_env) { if !ty.is_freeze(self.tcx, self.param_env) {
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
} }
@ -440,15 +442,19 @@ 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::Shallow | BorrowKind::Shared | BorrowKind::Unique BorrowKind::Shallow
| BorrowKind::Shared
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }
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)
} }
BorrowKind::Mut { .. } => { BorrowKind::Mut {
self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField) kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow,
} } => self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField),
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {} BorrowKind::Shallow
| BorrowKind::Shared
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {}
} }
} }
} }

View file

@ -1095,8 +1095,12 @@ impl<'tcx> Cx<'tcx> {
ty::UpvarCapture::ByRef(upvar_borrow) => { ty::UpvarCapture::ByRef(upvar_borrow) => {
let borrow_kind = match upvar_borrow { let borrow_kind = match upvar_borrow {
ty::BorrowKind::ImmBorrow => BorrowKind::Shared, ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique, ty::BorrowKind::UniqueImmBorrow => {
ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }, BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture }
}
ty::BorrowKind::MutBorrow => {
BorrowKind::Mut { kind: mir::MutBorrowKind::Default }
}
}; };
Expr { Expr {
temp_lifetime, temp_lifetime,
@ -1132,9 +1136,9 @@ impl ToBorrowKind for AutoBorrowMutability {
use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::adjustment::AllowTwoPhase;
match *self { match *self {
AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut { AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
allow_two_phase_borrow: match allow_two_phase_borrow { kind: match allow_two_phase_borrow {
AllowTwoPhase::Yes => true, AllowTwoPhase::Yes => mir::MutBorrowKind::TwoPhaseBorrow,
AllowTwoPhase::No => false, AllowTwoPhase::No => mir::MutBorrowKind::Default,
}, },
}, },
AutoBorrowMutability::Not => BorrowKind::Shared, AutoBorrowMutability::Not => BorrowKind::Shared,
@ -1145,7 +1149,7 @@ impl ToBorrowKind for AutoBorrowMutability {
impl ToBorrowKind for hir::Mutability { impl ToBorrowKind for hir::Mutability {
fn to_borrow_kind(&self) -> BorrowKind { fn to_borrow_kind(&self) -> BorrowKind {
match *self { match *self {
hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
hir::Mutability::Not => BorrowKind::Shared, hir::Mutability::Not => BorrowKind::Shared,
} }
} }

View file

@ -287,7 +287,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue), ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
ty::BindByReference(hir::Mutability::Mut) => ( ty::BindByReference(hir::Mutability::Mut) => (
Mutability::Not, Mutability::Not,
BindingMode::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false }), BindingMode::ByRef(BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
), ),
ty::BindByReference(hir::Mutability::Not) => { ty::BindByReference(hir::Mutability::Not) => {
(Mutability::Not, BindingMode::ByRef(BorrowKind::Shared)) (Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))

View file

@ -638,7 +638,7 @@ where
Place::from(ref_place), Place::from(ref_place),
Rvalue::Ref( Rvalue::Ref(
tcx.lifetimes.re_erased, tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false }, BorrowKind::Mut { kind: MutBorrowKind::Default },
self.place, self.place,
), ),
)], )],

View file

@ -522,7 +522,7 @@ impl<'tcx> Inliner<'tcx> {
trace!("creating temp for return destination"); trace!("creating temp for return destination");
let dest = Rvalue::Ref( let dest = Rvalue::Ref(
self.tcx.lifetimes.re_erased, self.tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false }, BorrowKind::Mut { kind: MutBorrowKind::Default },
destination, destination,
); );
let dest_ty = dest.ty(caller_body, self.tcx); let dest_ty = dest.ty(caller_body, self.tcx);

View file

@ -188,7 +188,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
// has been put into the body. // has been put into the body.
let reborrow = Rvalue::Ref( let reborrow = Rvalue::Ref(
tcx.lifetimes.re_erased, tcx.lifetimes.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false }, BorrowKind::Mut { kind: MutBorrowKind::Default },
tcx.mk_place_deref(dropee_ptr), tcx.mk_place_deref(dropee_ptr),
); );
let ref_ty = reborrow.ty(body.local_decls(), tcx); let ref_ty = reborrow.ty(body.local_decls(), tcx);
@ -712,7 +712,7 @@ fn build_call_shim<'tcx>(
) )
.immutable(), .immutable(),
); );
let borrow_kind = BorrowKind::Mut { allow_two_phase_borrow: false }; let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
statements.push(Statement { statements.push(Statement {
source_info, source_info,
kind: StatementKind::Assign(Box::new(( kind: StatementKind::Assign(Box::new((