Skip to content

Commit 6493ab6

Browse files
committed
Fixed incorrect reporting of errors when checking borrows in drops.
1 parent 673d97e commit 6493ab6

File tree

1 file changed

+41
-11
lines changed
  • src/librustc_mir/borrow_check

1 file changed

+41
-11
lines changed

src/librustc_mir/borrow_check/mod.rs

+41-11
Original file line numberDiff line numberDiff line change
@@ -2073,7 +2073,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20732073
/// currently in, when such distinction matters.
20742074
fn each_borrow_involving_path<F>(
20752075
&mut self,
2076-
_context: Context,
2076+
context: Context,
20772077
access_place: (ShallowOrDeep, &Place<'tcx>),
20782078
flow_state: &Flows<'cx, 'gcx, 'tcx>,
20792079
mut op: F,
@@ -2085,20 +2085,50 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20852085
// FIXME: analogous code in check_loans first maps `place` to
20862086
// its base_path.
20872087

2088+
// When this function is called as a result of an `access_terminator` call attempting
2089+
// to drop a struct, if that struct does not have a destructor, then we need to check
2090+
// each of the fields in the struct. See #47703.
2091+
let (access, places) = if let ContextKind::Drop = context.kind {
2092+
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
2093+
2094+
match ty.sty {
2095+
ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
2096+
let mut places = Vec::new();
2097+
2098+
for (index, field) in def.all_fields().enumerate() {
2099+
let proj = Projection {
2100+
base: place.clone(),
2101+
elem: ProjectionElem::Field(Field::new(index),
2102+
field.ty(self.tcx, substs)),
2103+
};
2104+
2105+
places.push(Place::Projection(Box::new(proj)));
2106+
}
2107+
2108+
(ShallowOrDeep::Shallow(None), places)
2109+
},
2110+
_ => (access, vec![ place.clone() ]),
2111+
}
2112+
} else {
2113+
(access, vec![ place.clone() ])
2114+
};
2115+
20882116
let data = flow_state.borrows.operator().borrows();
20892117

20902118
// check for loan restricting path P being used. Accounts for
20912119
// borrows of P, P.a.b, etc.
2092-
let mut elems_incoming = flow_state.borrows.elems_incoming();
2093-
while let Some(i) = elems_incoming.next() {
2094-
let borrowed = &data[i.borrow_index()];
2095-
2096-
if self.places_conflict(&borrowed.borrowed_place, place, access) {
2097-
debug!("each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
2098-
i, borrowed, place, access);
2099-
let ctrl = op(self, i, borrowed);
2100-
if ctrl == Control::Break {
2101-
return;
2120+
for place in places {
2121+
let mut elems_incoming = flow_state.borrows.elems_incoming();
2122+
while let Some(i) = elems_incoming.next() {
2123+
let borrowed = &data[i.borrow_index()];
2124+
2125+
if self.places_conflict(&borrowed.borrowed_place, &place, access) {
2126+
debug!("each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
2127+
i, borrowed, place, access);
2128+
let ctrl = op(self, i, borrowed);
2129+
if ctrl == Control::Break {
2130+
return;
2131+
}
21022132
}
21032133
}
21042134
}

0 commit comments

Comments
 (0)