diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs index 9a308586afff3..03d3b23bb23d5 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -93,9 +93,10 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { fn borrow( &mut self, place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>, - _diag_expr_id: HirId, + diag_expr_id: HirId, _bk: rustc_middle::ty::BorrowKind, ) { + debug!("borrow {:?}; diag_expr_id={:?}", place_with_id, diag_expr_id); self.places .borrowed .insert(TrackedValue::from_place_with_projections_allowed(place_with_id)); @@ -103,9 +104,14 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { fn mutate( &mut self, - _assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>, - _diag_expr_id: HirId, + assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>, + diag_expr_id: HirId, ) { + debug!("mutate {:?}; diag_expr_id={:?}", assignee_place, diag_expr_id); + // Count mutations as a borrow. + self.places + .borrowed + .insert(TrackedValue::from_place_with_projections_allowed(assignee_place)); } fn fake_read( diff --git a/src/test/ui/async-await/drop-track-field-assign-nonsend.rs b/src/test/ui/async-await/drop-track-field-assign-nonsend.rs new file mode 100644 index 0000000000000..b6c0fda15216a --- /dev/null +++ b/src/test/ui/async-await/drop-track-field-assign-nonsend.rs @@ -0,0 +1,45 @@ +// Derived from an ICE found in tokio-xmpp during a crater run. +// edition:2021 +// compile-flags: -Zdrop-tracking + +#![allow(dead_code)] + +#[derive(Clone)] +struct InfoResult { + node: Option> +} + +struct Agent { + info_result: InfoResult +} + +impl Agent { + async fn handle(&mut self) { + let mut info = self.info_result.clone(); + info.node = None; + let element = parse_info(info); + let _ = send_element(element).await; + } +} + +struct Element { +} + +async fn send_element(_: Element) {} + +fn parse(_: &[u8]) -> Result<(), ()> { + Ok(()) +} + +fn parse_info(_: InfoResult) -> Element { + Element { } +} + +fn assert_send(_: T) {} + +fn main() { + let agent = Agent { info_result: InfoResult { node: None } }; + // FIXME: It would be nice for this to work. See #94067. + assert_send(agent.handle()); + //~^ cannot be sent between threads safely +} diff --git a/src/test/ui/async-await/drop-track-field-assign-nonsend.stderr b/src/test/ui/async-await/drop-track-field-assign-nonsend.stderr new file mode 100644 index 0000000000000..d95483c81195c --- /dev/null +++ b/src/test/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -0,0 +1,25 @@ +error: future cannot be sent between threads safely + --> $DIR/drop-track-field-assign-nonsend.rs:43:17 + | +LL | assert_send(agent.handle()); + | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc` +note: future is not `Send` as this value is used across an await + --> $DIR/drop-track-field-assign-nonsend.rs:21:38 + | +LL | let mut info = self.info_result.clone(); + | -------- has type `InfoResult` which is not `Send` +... +LL | let _ = send_element(element).await; + | ^^^^^^ await occurs here, with `mut info` maybe used later +LL | } + | - `mut info` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/drop-track-field-assign-nonsend.rs:38:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/drop-track-field-assign.rs b/src/test/ui/async-await/drop-track-field-assign.rs new file mode 100644 index 0000000000000..3a393cd164b99 --- /dev/null +++ b/src/test/ui/async-await/drop-track-field-assign.rs @@ -0,0 +1,44 @@ +// Derived from an ICE found in tokio-xmpp during a crater run. +// edition:2021 +// compile-flags: -Zdrop-tracking +// build-pass + +#![allow(dead_code)] + +#[derive(Clone)] +struct InfoResult { + node: Option +} + +struct Agent { + info_result: InfoResult +} + +impl Agent { + async fn handle(&mut self) { + let mut info = self.info_result.clone(); + info.node = Some("bar".into()); + let element = parse_info(info); + let _ = send_element(element).await; + } +} + +struct Element { +} + +async fn send_element(_: Element) {} + +fn parse(_: &[u8]) -> Result<(), ()> { + Ok(()) +} + +fn parse_info(_: InfoResult) -> Element { + Element { } +} + +fn main() { + let mut agent = Agent { + info_result: InfoResult { node: None } + }; + let _ = agent.handle(); +}