From dcc2bdfd4cdd737d9a3032c95dbe60373de9381c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Apr 2021 10:36:54 -0600 Subject: [PATCH] Panic when awaiting conditions on dropped entities Co-Authored-By: Max Brunsfeld Co-Authored-By: Antonio Scandurra --- gpui/src/app.rs | 78 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 45fd1fb743fdee8d00861d8d19e0cdc3370e7266..a91a861eef1d188635a13accfd2461534cc9af31 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -2005,7 +2005,7 @@ impl ModelHandle { .or_insert_with(|| postage::broadcast::channel(128).0); let mut rx = tx.subscribe(); let ctx = ctx.weak_self.as_ref().unwrap().upgrade().unwrap(); - let handle = self.clone(); + let handle = self.downgrade(); async move { timeout(Duration::from_millis(200), async move { @@ -2013,14 +2013,20 @@ impl ModelHandle { { let ctx = ctx.borrow(); let ctx = ctx.as_ref(); - if predicate(handle.read(ctx), ctx) { + if predicate( + handle + .upgrade(ctx) + .expect("model dropped with pending condition") + .read(ctx), + ctx, + ) { break; } } - if rx.recv().await.is_none() { - panic!("model dropped with pending condition"); - } + rx.recv() + .await + .expect("model dropped with pending condition"); } }) .await @@ -2173,7 +2179,7 @@ impl ViewHandle { .or_insert_with(|| postage::broadcast::channel(128).0); let mut rx = tx.subscribe(); let ctx = ctx.weak_self.as_ref().unwrap().upgrade().unwrap(); - let handle = self.clone(); + let handle = self.downgrade(); async move { timeout(Duration::from_millis(200), async move { @@ -2181,14 +2187,20 @@ impl ViewHandle { { let ctx = ctx.borrow(); let ctx = ctx.as_ref(); - if predicate(handle.read(ctx), ctx) { + if predicate( + handle + .upgrade(ctx) + .expect("model dropped with pending condition") + .read(ctx), + ctx, + ) { break; } } - if rx.recv().await.is_none() { - panic!("model dropped with pending condition"); - } + rx.recv() + .await + .expect("model dropped with pending condition"); } }) .await @@ -3338,6 +3350,23 @@ mod tests { }); } + #[test] + #[should_panic(expected = "model dropped with pending condition")] + fn test_model_condition_panic_on_drop() { + struct Model; + + impl super::Entity for Model { + type Event = (); + } + + App::test_async((), |mut app| async move { + let model = app.add_model(|_| Model); + let condition = model.condition(&app, |_, _| false); + app.update(|_| drop(model)); + condition.await; + }); + } + #[test] fn test_view_condition() { struct Counter(usize); @@ -3408,6 +3437,35 @@ mod tests { }); } + #[test] + #[should_panic(expected = "model dropped with pending condition")] + fn test_view_condition_panic_on_drop() { + struct View; + + impl super::Entity for View { + type Event = (); + } + + impl super::View for View { + fn ui_name() -> &'static str { + "test view" + } + + fn render(&self, _: &AppContext) -> ElementBox { + Empty::new().boxed() + } + } + + App::test_async((), |mut app| async move { + let window_id = app.add_window(|_| View).0; + let view = app.add_view(window_id, |_| View); + + let condition = view.condition(&app, |_, _| false); + app.update(|_| drop(view)); + condition.await; + }); + } + // #[test] // fn test_ui_and_window_updates() { // struct View {