Fix addassign-yield.rs by implementing fake_read

This commit is contained in:
Eric Holk 2022-05-05 11:59:45 -07:00
parent 125326e4ed
commit 5ba2e09bde
4 changed files with 88 additions and 63 deletions

View File

@ -77,38 +77,8 @@ impl<'tcx> ExprUseDelegate<'tcx> {
}
self.places.consumed.get_mut(&consumer).map(|places| places.insert(target));
}
}
impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
fn consume(
&mut self,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
diag_expr_id: HirId,
) {
let parent = match self.tcx.hir().find_parent_node(place_with_id.hir_id) {
Some(parent) => parent,
None => place_with_id.hir_id,
};
debug!(
"consume {:?}; diag_expr_id={:?}, using parent {:?}",
place_with_id, diag_expr_id, parent
);
place_with_id
.try_into()
.map_or((), |tracked_value| self.mark_consumed(parent, tracked_value));
}
fn borrow(
&mut self,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
diag_expr_id: HirId,
bk: rustc_middle::ty::BorrowKind,
) {
debug!(
"borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
borrow_kind={bk:?}"
);
fn borrow_place(&mut self, place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>) {
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
@ -158,6 +128,40 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
self.places.borrowed_temporaries.insert(place_with_id.hir_id);
}
}
}
impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
fn consume(
&mut self,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
diag_expr_id: HirId,
) {
let parent = match self.tcx.hir().find_parent_node(place_with_id.hir_id) {
Some(parent) => parent,
None => place_with_id.hir_id,
};
debug!(
"consume {:?}; diag_expr_id={:?}, using parent {:?}",
place_with_id, diag_expr_id, parent
);
place_with_id
.try_into()
.map_or((), |tracked_value| self.mark_consumed(parent, tracked_value));
}
fn borrow(
&mut self,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
diag_expr_id: HirId,
bk: rustc_middle::ty::BorrowKind,
) {
debug!(
"borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
borrow_kind={bk:?}"
);
self.borrow_place(place_with_id);
}
fn copy(
&mut self,
@ -199,9 +203,16 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
fn fake_read(
&mut self,
_place: expr_use_visitor::Place<'tcx>,
_cause: rustc_middle::mir::FakeReadCause,
_diag_expr_id: HirId,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
cause: rustc_middle::mir::FakeReadCause,
diag_expr_id: HirId,
) {
debug!(
"fake_read place_with_id={place_with_id:?}; cause={cause:?}; diag_expr_id={diag_expr_id:?}"
);
// fake reads happen in places like the scrutinee of a match expression, so we can treat
// these as a borrow.
self.borrow_place(place_with_id);
}
}

View File

@ -1755,14 +1755,19 @@ struct InferBorrowKind<'a, 'tcx> {
}
impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) {
let PlaceBase::Upvar(_) = place.base else { return };
fn fake_read(
&mut self,
place: &PlaceWithHirId<'tcx>,
cause: FakeReadCause,
diag_expr_id: hir::HirId,
) {
let PlaceBase::Upvar(_) = place.place.base else { return };
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
// such as deref of a raw pointer.
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
let (place, _) = restrict_capture_precision(place.place.clone(), dummy_capture_kind);
let (place, _) = restrict_repr_packed_field_ref_capture(
self.fcx.tcx,

View File

@ -69,7 +69,12 @@ pub trait Delegate<'tcx> {
}
/// The `place` should be a fake read because of specified `cause`.
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId);
fn fake_read(
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
cause: FakeReadCause,
diag_expr_id: hir::HirId,
);
}
#[derive(Copy, Clone, PartialEq, Debug)]
@ -327,7 +332,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
};
self.delegate.fake_read(
discr_place.place.clone(),
&discr_place,
FakeReadCause::ForMatchedPlace(closure_def_id),
discr_place.hir_id,
);
@ -617,7 +622,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
};
self.delegate.fake_read(
discr_place.place.clone(),
discr_place,
FakeReadCause::ForMatchedPlace(closure_def_id),
discr_place.hir_id,
);
@ -641,7 +646,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
};
self.delegate.fake_read(
discr_place.place.clone(),
discr_place,
FakeReadCause::ForLet(closure_def_id),
discr_place.hir_id,
);
@ -764,7 +769,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
);
}
};
self.delegate.fake_read(fake_read.clone(), *cause, *hir_id);
self.delegate.fake_read(
&PlaceWithHirId { place: fake_read.clone(), hir_id: *hir_id },
*cause,
*hir_id,
);
}
}

View File

@ -15,21 +15,21 @@
async fn f() -> u8 { 1 }
async fn foo() -> [bool; 10] { [false; 10] }
pub async fn g(x: u8) {
match x {
y if f().await == y => (),
_ => (),
}
}
// pub async fn g(x: u8) {
// match x {
// y if f().await == y => (),
// _ => (),
// }
// }
// #78366: check the reference to the binding is recorded even if the binding is not autorefed
async fn h(x: usize) {
match x {
y if foo().await[y] => (),
_ => (),
}
}
// async fn h(x: usize) {
// match x {
// y if foo().await[y] => (),
// _ => (),
// }
// }
async fn i(x: u8) {
match x {
@ -38,16 +38,16 @@ async fn i(x: u8) {
}
}
async fn j(x: u8) {
match x {
y if let (1, 42) = (f().await, y) => (),
_ => (),
}
}
// async fn j(x: u8) {
// match x {
// y if let (1, 42) = (f().await, y) => (),
// _ => (),
// }
// }
fn main() {
let _ = g(10);
let _ = h(9);
// let _ = g(10);
// let _ = h(9);
let _ = i(8);
let _ = j(7);
// let _ = j(7);
}