Skip to content

Commit 02f5786

Browse files
committed
Auto merge of #61151 - Centril:rollup-5rpyhfo, r=Centril
Rollup of 6 pull requests Successful merges: - #61092 (Make sanitize_place iterate instead of recurse) - #61093 (Make borrow_of_local_data iterate instead of recurse) - #61094 (Make find_local iterate instead of recurse) - #61099 (Make ignore_borrow iterate instead of recurse) - #61103 (Make find iterate instead of recurse) - #61104 (Make eval_place_to_op iterate instead of recurse) Failed merges: r? @ghost
2 parents 315ab95 + 1cd3ddd commit 02f5786

File tree

7 files changed

+188
-173
lines changed

7 files changed

+188
-173
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+78-75
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionV
2929
use rustc::infer::type_variable::TypeVariableOrigin;
3030
use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
3131
use rustc::mir::tcx::PlaceTy;
32-
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
32+
use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
3333
use rustc::mir::*;
3434
use rustc::traits::query::type_op;
3535
use rustc::traits::query::type_op::custom::CustomTypeOp;
@@ -447,92 +447,95 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
447447
context: PlaceContext,
448448
) -> PlaceTy<'tcx> {
449449
debug!("sanitize_place: {:?}", place);
450-
let place_ty = match place {
451-
Place::Base(PlaceBase::Local(index)) =>
452-
PlaceTy::from_ty(self.mir.local_decls[*index].ty),
453-
Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
454-
let sty = self.sanitize_type(place, sty);
455-
let check_err =
456-
|verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
457-
place: &Place<'tcx>,
458-
ty,
459-
sty| {
460-
if let Err(terr) = verifier.cx.eq_types(
461-
sty,
462-
ty,
463-
location.to_locations(),
464-
ConstraintCategory::Boring,
465-
) {
466-
span_mirbug!(
467-
verifier,
468-
place,
469-
"bad promoted type ({:?}: {:?}): {:?}",
470-
ty,
471-
sty,
472-
terr
473-
);
450+
451+
place.iterate(|place_base, place_projection| {
452+
let mut place_ty = match place_base {
453+
PlaceBase::Local(index) =>
454+
PlaceTy::from_ty(self.mir.local_decls[*index].ty),
455+
PlaceBase::Static(box Static { kind, ty: sty }) => {
456+
let sty = self.sanitize_type(place, sty);
457+
let check_err =
458+
|verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
459+
place: &Place<'tcx>,
460+
ty,
461+
sty| {
462+
if let Err(terr) = verifier.cx.eq_types(
463+
sty,
464+
ty,
465+
location.to_locations(),
466+
ConstraintCategory::Boring,
467+
) {
468+
span_mirbug!(
469+
verifier,
470+
place,
471+
"bad promoted type ({:?}: {:?}): {:?}",
472+
ty,
473+
sty,
474+
terr
475+
);
476+
};
474477
};
475-
};
476-
match kind {
477-
StaticKind::Promoted(promoted) => {
478-
if !self.errors_reported {
479-
let promoted_mir = &self.mir.promoted[*promoted];
480-
self.sanitize_promoted(promoted_mir, location);
481-
482-
let promoted_ty = promoted_mir.return_ty();
483-
check_err(self, place, promoted_ty, sty);
478+
match kind {
479+
StaticKind::Promoted(promoted) => {
480+
if !self.errors_reported {
481+
let promoted_mir = &self.mir.promoted[*promoted];
482+
self.sanitize_promoted(promoted_mir, location);
483+
484+
let promoted_ty = promoted_mir.return_ty();
485+
check_err(self, place, promoted_ty, sty);
486+
}
484487
}
485-
}
486-
StaticKind::Static(def_id) => {
487-
let ty = self.tcx().type_of(*def_id);
488-
let ty = self.cx.normalize(ty, location);
488+
StaticKind::Static(def_id) => {
489+
let ty = self.tcx().type_of(*def_id);
490+
let ty = self.cx.normalize(ty, location);
489491

490-
check_err(self, place, ty, sty);
492+
check_err(self, place, ty, sty);
493+
}
491494
}
495+
PlaceTy::from_ty(sty)
496+
}
497+
};
498+
499+
// FIXME use place_projection.is_empty() when is available
500+
if let Place::Base(_) = place {
501+
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
502+
let tcx = self.tcx();
503+
let trait_ref = ty::TraitRef {
504+
def_id: tcx.lang_items().copy_trait().unwrap(),
505+
substs: tcx.mk_substs_trait(place_ty.ty, &[]),
506+
};
507+
508+
// In order to have a Copy operand, the type T of the
509+
// value must be Copy. Note that we prove that T: Copy,
510+
// rather than using the `is_copy_modulo_regions`
511+
// test. This is important because
512+
// `is_copy_modulo_regions` ignores the resulting region
513+
// obligations and assumes they pass. This can result in
514+
// bounds from Copy impls being unsoundly ignored (e.g.,
515+
// #29149). Note that we decide to use Copy before knowing
516+
// whether the bounds fully apply: in effect, the rule is
517+
// that if a value of some type could implement Copy, then
518+
// it must.
519+
self.cx.prove_trait_ref(
520+
trait_ref,
521+
location.to_locations(),
522+
ConstraintCategory::CopyBound,
523+
);
492524
}
493-
PlaceTy::from_ty(sty)
494525
}
495-
Place::Projection(ref proj) => {
496-
let base_context = if context.is_mutating_use() {
497-
PlaceContext::MutatingUse(MutatingUseContext::Projection)
498-
} else {
499-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
500-
};
501-
let base_ty = self.sanitize_place(&proj.base, location, base_context);
502-
if base_ty.variant_index.is_none() {
503-
if base_ty.ty.references_error() {
526+
527+
for proj in place_projection {
528+
if place_ty.variant_index.is_none() {
529+
if place_ty.ty.references_error() {
504530
assert!(self.errors_reported);
505531
return PlaceTy::from_ty(self.tcx().types.err);
506532
}
507533
}
508-
self.sanitize_projection(base_ty, &proj.elem, place, location)
534+
place_ty = self.sanitize_projection(place_ty, &proj.elem, place, location)
509535
}
510-
};
511-
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
512-
let tcx = self.tcx();
513-
let trait_ref = ty::TraitRef {
514-
def_id: tcx.lang_items().copy_trait().unwrap(),
515-
substs: tcx.mk_substs_trait(place_ty.ty, &[]),
516-
};
517536

518-
// In order to have a Copy operand, the type T of the
519-
// value must be Copy. Note that we prove that T: Copy,
520-
// rather than using the `is_copy_modulo_regions`
521-
// test. This is important because
522-
// `is_copy_modulo_regions` ignores the resulting region
523-
// obligations and assumes they pass. This can result in
524-
// bounds from Copy impls being unsoundly ignored (e.g.,
525-
// #29149). Note that we decide to use Copy before knowing
526-
// whether the bounds fully apply: in effect, the rule is
527-
// that if a value of some type could implement Copy, then
528-
// it must.
529-
self.cx.prove_trait_ref(
530-
trait_ref,
531-
location.to_locations(),
532-
ConstraintCategory::CopyBound,
533-
);
534-
}
535-
place_ty
537+
place_ty
538+
})
536539
}
537540

538541
fn sanitize_promoted(&mut self, promoted_mir: &'b Mir<'tcx>, location: Location) {

src/librustc_mir/borrow_check/path_utils.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -131,22 +131,20 @@ pub(super) fn is_active<'tcx>(
131131
/// Determines if a given borrow is borrowing local data
132132
/// This is called for all Yield statements on movable generators
133133
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
134-
match place {
135-
Place::Base(PlaceBase::Static(..)) => false,
136-
Place::Base(PlaceBase::Local(..)) => true,
137-
Place::Projection(box proj) => {
138-
match proj.elem {
139-
// Reborrow of already borrowed data is ignored
140-
// Any errors will be caught on the initial borrow
141-
ProjectionElem::Deref => false,
134+
place.iterate(|place_base, place_projection| {
135+
match place_base {
136+
PlaceBase::Static(..) => return false,
137+
PlaceBase::Local(..) => {},
138+
}
142139

143-
// For interior references and downcasts, find out if the base is local
144-
ProjectionElem::Field(..)
145-
| ProjectionElem::Index(..)
146-
| ProjectionElem::ConstantIndex { .. }
147-
| ProjectionElem::Subslice { .. }
148-
| ProjectionElem::Downcast(..) => borrow_of_local_data(&proj.base),
140+
for proj in place_projection {
141+
// Reborrow of already borrowed data is ignored
142+
// Any errors will be caught on the initial borrow
143+
if proj.elem == ProjectionElem::Deref {
144+
return false;
149145
}
150146
}
151-
}
147+
148+
true
149+
})
152150
}

src/librustc_mir/borrow_check/place_ext.rs

+33-35
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,36 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
2525
mir: &Mir<'tcx>,
2626
locals_state_at_exit: &LocalsStateAtExit,
2727
) -> bool {
28-
match self {
29-
// If a local variable is immutable, then we only need to track borrows to guard
30-
// against two kinds of errors:
31-
// * The variable being dropped while still borrowed (e.g., because the fn returns
32-
// a reference to a local variable)
33-
// * The variable being moved while still borrowed
34-
//
35-
// In particular, the variable cannot be mutated -- the "access checks" will fail --
36-
// so we don't have to worry about mutation while borrowed.
37-
Place::Base(PlaceBase::Local(index)) => {
38-
match locals_state_at_exit {
39-
LocalsStateAtExit::AllAreInvalidated => false,
40-
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
41-
let ignore = !has_storage_dead_or_moved.contains(*index) &&
42-
mir.local_decls[*index].mutability == Mutability::Not;
43-
debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
44-
ignore
28+
self.iterate(|place_base, place_projection| {
29+
let ignore = match place_base {
30+
// If a local variable is immutable, then we only need to track borrows to guard
31+
// against two kinds of errors:
32+
// * The variable being dropped while still borrowed (e.g., because the fn returns
33+
// a reference to a local variable)
34+
// * The variable being moved while still borrowed
35+
//
36+
// In particular, the variable cannot be mutated -- the "access checks" will fail --
37+
// so we don't have to worry about mutation while borrowed.
38+
PlaceBase::Local(index) => {
39+
match locals_state_at_exit {
40+
LocalsStateAtExit::AllAreInvalidated => false,
41+
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
42+
let ignore = !has_storage_dead_or_moved.contains(*index) &&
43+
mir.local_decls[*index].mutability == Mutability::Not;
44+
debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
45+
ignore
46+
}
4547
}
4648
}
47-
}
48-
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
49-
false,
50-
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
51-
tcx.is_mutable_static(*def_id)
52-
}
53-
Place::Projection(proj) => match proj.elem {
54-
ProjectionElem::Field(..)
55-
| ProjectionElem::Downcast(..)
56-
| ProjectionElem::Subslice { .. }
57-
| ProjectionElem::ConstantIndex { .. }
58-
| ProjectionElem::Index(_) => proj.base.ignore_borrow(
59-
tcx, mir, locals_state_at_exit),
49+
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) =>
50+
false,
51+
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
52+
tcx.is_mutable_static(*def_id)
53+
}
54+
};
6055

61-
ProjectionElem::Deref => {
56+
for proj in place_projection {
57+
if proj.elem == ProjectionElem::Deref {
6258
let ty = proj.base.ty(mir, tcx).ty;
6359
match ty.sty {
6460
// For both derefs of raw pointers and `&T`
@@ -71,11 +67,13 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
7167
// original path into a new variable and
7268
// borrowed *that* one, leaving the original
7369
// path unborrowed.
74-
ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => true,
75-
_ => proj.base.ignore_borrow(tcx, mir, locals_state_at_exit),
70+
ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => return true,
71+
_ => {}
7672
}
7773
}
78-
},
79-
}
74+
}
75+
76+
ignore
77+
})
8078
}
8179
}

src/librustc_mir/dataflow/impls/borrowed_locals.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,19 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
9191
}
9292

9393
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
94-
match *place {
95-
Place::Base(PlaceBase::Local(l)) => Some(l),
96-
Place::Base(PlaceBase::Static(..)) => None,
97-
Place::Projection(ref proj) => {
98-
match proj.elem {
99-
ProjectionElem::Deref => None,
100-
_ => find_local(&proj.base)
94+
place.iterate(|place_base, place_projection| {
95+
for proj in place_projection {
96+
if proj.elem == ProjectionElem::Deref {
97+
return None;
10198
}
10299
}
103-
}
100+
101+
if let PlaceBase::Local(local) = place_base {
102+
Some(*local)
103+
} else {
104+
None
105+
}
106+
})
104107
}
105108

106109
impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {

src/librustc_mir/dataflow/move_paths/mod.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -241,21 +241,22 @@ impl MovePathLookup {
241241
// unknown place, but will rather return the nearest available
242242
// parent.
243243
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
244-
match *place {
245-
Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
246-
Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
247-
Place::Projection(ref proj) => {
248-
match self.find(&proj.base) {
249-
LookupResult::Exact(base_path) => {
250-
match self.projections.get(&(base_path, proj.elem.lift())) {
251-
Some(&subpath) => LookupResult::Exact(subpath),
252-
None => LookupResult::Parent(Some(base_path))
253-
}
254-
}
255-
inexact => inexact
244+
place.iterate(|place_base, place_projection| {
245+
let mut result = match place_base {
246+
PlaceBase::Local(local) => self.locals[*local],
247+
PlaceBase::Static(..) => return LookupResult::Parent(None),
248+
};
249+
250+
for proj in place_projection {
251+
if let Some(&subpath) = self.projections.get(&(result, proj.elem.lift())) {
252+
result = subpath;
253+
} else {
254+
return LookupResult::Parent(Some(result));
256255
}
257256
}
258-
}
257+
258+
LookupResult::Exact(result)
259+
})
259260
}
260261

261262
pub fn find_local(&self, local: Local) -> MovePathIndex {

0 commit comments

Comments
 (0)