Skip to content

Commit c00266b

Browse files
committed
Encode (in MIR) whether borrows are explicit in source or arise due to autoref.
This is foundation for issue 46747 (limit two-phase borrows to method-call autorefs).
1 parent 4f93357 commit c00266b

File tree

14 files changed

+67
-35
lines changed

14 files changed

+67
-35
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use std::mem;
2020
impl_stable_hash_for!(struct mir::GeneratorLayout<'tcx> { fields });
2121
impl_stable_hash_for!(struct mir::SourceInfo { span, scope });
2222
impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
23-
impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
2423
impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
2524
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
2625
mutability,
@@ -36,6 +35,25 @@ impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator,
3635
impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind });
3736
impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
3837

38+
impl<'gcx> HashStable<StableHashingContext<'gcx>>
39+
for mir::BorrowKind {
40+
#[inline]
41+
fn hash_stable<W: StableHasherResult>(&self,
42+
hcx: &mut StableHashingContext<'gcx>,
43+
hasher: &mut StableHasher<W>) {
44+
mem::discriminant(self).hash_stable(hcx, hasher);
45+
46+
match *self {
47+
mir::BorrowKind::Shared |
48+
mir::BorrowKind::Unique => {}
49+
mir::BorrowKind::Mut { allow_two_phase_borrow } => {
50+
allow_two_phase_borrow.hash_stable(hcx, hasher);
51+
}
52+
}
53+
}
54+
}
55+
56+
3957
impl<'gcx> HashStable<StableHashingContext<'gcx>>
4058
for mir::UnsafetyViolationKind {
4159
#[inline]

src/librustc/mir/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,11 @@ pub enum BorrowKind {
413413
Unique,
414414

415415
/// Data is mutable and not aliasable.
416-
Mut,
416+
Mut {
417+
/// True if this borrow arose from method-call auto-ref
418+
/// (i.e. `adjustment::Adjust::Borrow`)
419+
allow_two_phase_borrow: bool
420+
}
417421
}
418422

419423
///////////////////////////////////////////////////////////////////////////
@@ -1611,7 +1615,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
16111615
Ref(region, borrow_kind, ref place) => {
16121616
let kind_str = match borrow_kind {
16131617
BorrowKind::Shared => "",
1614-
BorrowKind::Mut | BorrowKind::Unique => "mut ",
1618+
BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
16151619
};
16161620

16171621
// When printing regions, add trailing space if necessary.

src/librustc/mir/tcx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl<'tcx> BinOp {
264264
impl BorrowKind {
265265
pub fn to_mutbl_lossy(self) -> hir::Mutability {
266266
match self {
267-
BorrowKind::Mut => hir::MutMutable,
267+
BorrowKind::Mut { .. } => hir::MutMutable,
268268
BorrowKind::Shared => hir::MutImmutable,
269269

270270
// We have no type corresponding to a unique imm borrow, so

src/librustc/mir/visit.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -951,9 +951,10 @@ impl<'tcx> PlaceContext<'tcx> {
951951
pub fn is_mutating_use(&self) -> bool {
952952
match *self {
953953
PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call |
954-
PlaceContext::Borrow { kind: BorrowKind::Mut, .. } |
954+
PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } |
955955
PlaceContext::Projection(Mutability::Mut) |
956956
PlaceContext::Drop => true,
957+
957958
PlaceContext::Inspect |
958959
PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
959960
PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
@@ -971,7 +972,8 @@ impl<'tcx> PlaceContext<'tcx> {
971972
PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
972973
PlaceContext::Projection(Mutability::Not) |
973974
PlaceContext::Copy | PlaceContext::Move => true,
974-
PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Store |
975+
976+
PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store |
975977
PlaceContext::AsmOutput |
976978
PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) |
977979
PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead |

src/librustc_const_eval/pattern.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
134134
BindingMode::ByValue => mutability == Mutability::Mut,
135135
BindingMode::ByRef(_, bk) => {
136136
write!(f, "ref ")?;
137-
bk == BorrowKind::Mut
137+
match bk { BorrowKind::Mut { .. } => true, _ => false }
138138
}
139139
};
140140
if is_mut {
@@ -429,7 +429,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
429429
(Mutability::Not, BindingMode::ByValue),
430430
ty::BindByReference(hir::MutMutable) =>
431431
(Mutability::Not, BindingMode::ByRef(
432-
region.unwrap(), BorrowKind::Mut)),
432+
region.unwrap(), BorrowKind::Mut { allow_two_phase_borrow: false })),
433433
ty::BindByReference(hir::MutImmutable) =>
434434
(Mutability::Not, BindingMode::ByRef(
435435
region.unwrap(), BorrowKind::Shared)),

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
256256
"immutable",
257257
"mutable",
258258
) {
259-
(BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
260-
(BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
259+
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
260+
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
261261
.cannot_reborrow_already_borrowed(
262262
span,
263263
&desc_place,
@@ -271,7 +271,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
271271
Origin::Mir,
272272
),
273273

274-
(BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) => self.tcx
274+
(BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => self.tcx
275275
.cannot_mutably_borrow_multiply(
276276
span,
277277
&desc_place,
@@ -314,7 +314,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
314314
Origin::Mir,
315315
),
316316

317-
(BorrowKind::Mut, _, lft, BorrowKind::Unique, _, _) => self.tcx
317+
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => self.tcx
318318
.cannot_reborrow_already_uniquely_borrowed(
319319
span,
320320
&desc_place,

src/librustc_mir/borrow_check/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
797797
Control::Continue
798798
}
799799

800-
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => {
800+
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
801801
// Reading from mere reservations of mutable-borrows is OK.
802802
if this.tcx.sess.two_phase_borrows() && index.is_reservation()
803803
{
@@ -828,7 +828,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
828828
}
829829

830830
(Reservation(kind), BorrowKind::Unique)
831-
| (Reservation(kind), BorrowKind::Mut)
831+
| (Reservation(kind), BorrowKind::Mut { .. })
832832
| (Activation(kind, _), _)
833833
| (Write(kind), _) => {
834834
match rw {
@@ -945,7 +945,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
945945
Rvalue::Ref(_ /*rgn*/, bk, ref place) => {
946946
let access_kind = match bk {
947947
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
948-
BorrowKind::Unique | BorrowKind::Mut => {
948+
BorrowKind::Unique | BorrowKind::Mut { .. } => {
949949
let wk = WriteKind::MutableBorrow(bk);
950950
if self.tcx.sess.two_phase_borrows() {
951951
(Deep, Reservation(wk))
@@ -1196,7 +1196,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11961196
// mutable borrow before we check it.
11971197
match borrow.kind {
11981198
BorrowKind::Shared => return,
1199-
BorrowKind::Unique | BorrowKind::Mut => {}
1199+
BorrowKind::Unique | BorrowKind::Mut { .. } => {}
12001200
}
12011201

12021202
self.access_place(
@@ -1467,8 +1467,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
14671467
span_bug!(span, "&unique borrow for {:?} should not fail", place);
14681468
}
14691469
}
1470-
Reservation(WriteKind::MutableBorrow(BorrowKind::Mut))
1471-
| Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => if let Err(place_err) =
1470+
Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
1471+
| Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) =
14721472
self.is_mutable(place, is_local_mutation_allowed)
14731473
{
14741474
error_reported = true;
@@ -1532,7 +1532,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15321532
Activation(..) => {} // permission checks are done at Reservation point.
15331533

15341534
Read(ReadKind::Borrow(BorrowKind::Unique))
1535-
| Read(ReadKind::Borrow(BorrowKind::Mut))
1535+
| Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
15361536
| Read(ReadKind::Borrow(BorrowKind::Shared))
15371537
| Read(ReadKind::Copy) => {} // Access authorized
15381538
}

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
122122
let kind = match self.kind {
123123
mir::BorrowKind::Shared => "",
124124
mir::BorrowKind::Unique => "uniq ",
125-
mir::BorrowKind::Mut => "mut ",
125+
mir::BorrowKind::Mut { .. } => "mut ",
126126
};
127127
let region = format!("{}", self.region);
128128
let region = if region.len() > 0 { format!("{} ", region) } else { region };

src/librustc_mir/hair/cx/expr.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
2121
use rustc::ty::cast::CastKind as TyCastKind;
2222
use rustc::hir;
2323
use rustc::hir::def_id::LocalDefId;
24+
use rustc::mir::{BorrowKind};
2425

2526
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
2627
type Output = Expr<'tcx>;
@@ -111,7 +112,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
111112
span,
112113
kind: ExprKind::Borrow {
113114
region: deref.region,
114-
borrow_kind: to_borrow_kind(deref.mutbl),
115+
borrow_kind: to_borrow_kind(deref.mutbl, true),
115116
arg: expr.to_ref(),
116117
},
117118
};
@@ -121,7 +122,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
121122
Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
122123
ExprKind::Borrow {
123124
region: r,
124-
borrow_kind: to_borrow_kind(m),
125+
borrow_kind: to_borrow_kind(m, true),
125126
arg: expr.to_ref(),
126127
}
127128
}
@@ -141,7 +142,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
141142
span,
142143
kind: ExprKind::Borrow {
143144
region,
144-
borrow_kind: to_borrow_kind(m),
145+
borrow_kind: to_borrow_kind(m, true),
145146
arg: expr.to_ref(),
146147
},
147148
};
@@ -287,7 +288,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
287288
};
288289
ExprKind::Borrow {
289290
region,
290-
borrow_kind: to_borrow_kind(mutbl),
291+
borrow_kind: to_borrow_kind(mutbl, false),
291292
arg: expr.to_ref(),
292293
}
293294
}
@@ -642,9 +643,9 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
642643
}
643644
}
644645

645-
fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
646+
fn to_borrow_kind(m: hir::Mutability, allow_two_phase_borrow: bool) -> BorrowKind {
646647
match m {
647-
hir::MutMutable => BorrowKind::Mut,
648+
hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow },
648649
hir::MutImmutable => BorrowKind::Shared,
649650
}
650651
}
@@ -947,7 +948,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
947948
let borrow_kind = match upvar_borrow.kind {
948949
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
949950
ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
950-
ty::BorrowKind::MutBorrow => BorrowKind::Mut,
951+
ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }
951952
};
952953
Expr {
953954
temp_lifetime,

src/librustc_mir/shim.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,11 +716,14 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
716716
}),
717717
span
718718
));
719+
let borrow_kind = BorrowKind::Mut {
720+
allow_two_phase_borrow: false,
721+
};
719722
statements.push(Statement {
720723
source_info,
721724
kind: StatementKind::Assign(
722725
Place::Local(ref_rcvr),
723-
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l)
726+
Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
724727
)
725728
});
726729
Operand::Move(Place::Local(ref_rcvr))

src/librustc_mir/transform/inline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
426426
debug!("Creating temp for return destination");
427427
let dest = Rvalue::Ref(
428428
self.tcx.types.re_erased,
429-
BorrowKind::Mut,
429+
BorrowKind::Mut { allow_two_phase_borrow: false },
430430
destination.0);
431431

432432
let ty = dest.ty(caller_mir, self.tcx);
@@ -511,7 +511,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
511511
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
512512
let arg = Rvalue::Ref(
513513
self.tcx.types.re_erased,
514-
BorrowKind::Mut,
514+
BorrowKind::Mut { allow_two_phase_borrow: false },
515515
arg.deref());
516516

517517
let ty = arg.ty(caller_mir, self.tcx);

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
600600
}
601601

602602
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
603-
if kind == BorrowKind::Mut {
603+
if let BorrowKind::Mut { .. } = kind {
604604
// In theory, any zero-sized value could be borrowed
605605
// mutably without consequences. However, only &mut []
606606
// is allowed right now, and only in functions.

src/librustc_mir/util/elaborate_drops.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
531531
let result = BasicBlockData {
532532
statements: vec![self.assign(
533533
&Place::Local(ref_place),
534-
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.place.clone())
534+
Rvalue::Ref(tcx.types.re_erased,
535+
BorrowKind::Mut { allow_two_phase_borrow: false },
536+
self.place.clone())
535537
)],
536538
terminator: Some(Terminator {
537539
kind: TerminatorKind::Call {
@@ -591,7 +593,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
591593
} else {
592594
(Rvalue::Ref(
593595
tcx.types.re_erased,
594-
BorrowKind::Mut,
596+
BorrowKind::Mut { allow_two_phase_borrow: false },
595597
self.place.clone().index(cur)),
596598
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
597599
};
@@ -735,7 +737,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
735737
// cur = tmp as *mut T;
736738
// end = Offset(cur, len);
737739
drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
738-
tcx.types.re_erased, BorrowKind::Mut, self.place.clone()
740+
tcx.types.re_erased,
741+
BorrowKind::Mut { allow_two_phase_borrow: false },
742+
self.place.clone()
739743
)));
740744
drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
741745
CastKind::Misc, Operand::Move(tmp.clone()), iter_ty

src/librustc_trans/mir/constant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
870870
} else {
871871
self.cx.tcx.data_layout.pointer_align
872872
};
873-
if bk == mir::BorrowKind::Mut {
873+
if let mir::BorrowKind::Mut { .. } = bk {
874874
consts::addr_of_mut(self.cx, llval, align, "ref_mut")
875875
} else {
876876
consts::addr_of(self.cx, llval, align, "ref")

0 commit comments

Comments
 (0)