From 337697a8866c524df503b099ed060fb808615cdd Mon Sep 17 00:00:00 2001 From: niedzwiedzw Date: Thu, 13 Jul 2023 20:12:28 +0200 Subject: [PATCH] test with forked version of debug-cell --- packages/hooks/Cargo.toml | 6 +- packages/hooks/src/lib.rs | 2 + packages/hooks/src/use_shared_state.rs | 154 +++++-------------------- 3 files changed, 35 insertions(+), 127 deletions(-) diff --git a/packages/hooks/Cargo.toml b/packages/hooks/Cargo.toml index b2dd4898f..7bb40c5f3 100644 --- a/packages/hooks/Cargo.toml +++ b/packages/hooks/Cargo.toml @@ -9,16 +9,18 @@ repository = "https://github.com/DioxusLabs/dioxus/" homepage = "https://dioxuslabs.com" keywords = ["dom", "ui", "gui", "react"] +[features] +default = [] +nightly-features = [] [dependencies] dioxus-core = { workspace = true } futures-channel = { workspace = true } log = { workspace = true } thiserror = { workspace = true } - +debug-cell = { git = "https://github.com/Niedzwiedzw/debug-cell", rev = "3352a1f8aff19f56f5e3b2018200a3338fd43d2e" } # waiting for the merge / official DioxusLabs fork [dev-dependencies] futures-util = { workspace = true, default-features = false } dioxus-core = { workspace = true } dioxus = { workspace = true } -debug-cell = "0.1.1" diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 21795a9d6..9589c5f72 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "nightly-features", feature(debug_refcell))] + #[macro_export] /// A helper macro for using hooks and properties in async environements. /// diff --git a/packages/hooks/src/use_shared_state.rs b/packages/hooks/src/use_shared_state.rs index cd5909d57..bde1fabb8 100644 --- a/packages/hooks/src/use_shared_state.rs +++ b/packages/hooks/src/use_shared_state.rs @@ -1,17 +1,15 @@ use self::error::{UseSharedStateError, UseSharedStateResult}; use dioxus_core::{ScopeId, ScopeState}; -use std::{ - cell::{Ref, RefCell, RefMut}, - collections::HashSet, - rc::Rc, - sync::Arc, +use std::{collections::HashSet, rc::Rc, sync::Arc}; + +#[cfg(debug_assertions)] +pub use debug_cell::{ + error::{BorrowError, BorrowMutError}, + Ref, RefCell, RefMut, }; #[cfg(not(debug_assertions))] -type Location = (); - -#[cfg(debug_assertions)] -type Location = &'static std::panic::Location<'static>; +pub use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut}; #[macro_export] macro_rules! debug_location { @@ -27,119 +25,49 @@ macro_rules! debug_location { }}; } -pub mod diagnostics { - use std::panic::Location; - - #[derive(Debug, Clone, Copy)] - pub enum BorrowKind { - Mutable, - Immutable, - } - - #[derive(Debug, Clone, Copy)] - pub struct PreviousBorrow { - pub location: Location<'static>, - pub kind: BorrowKind, - } - - impl PreviousBorrow { - pub fn display_opt(value: &Option) -> String { - value - .as_ref() - .map(|value| value.to_string()) - .unwrap_or_default() - } - } - - impl std::fmt::Display for PreviousBorrow { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { location, kind } = self; - write!(f, "{location} ({kind:?})") - } - } - - impl super::UseSharedState { - #[cfg_attr(debug_assertions, track_caller)] - #[cfg_attr(debug_assertions, inline(never))] - #[allow(unused_must_use)] - pub(super) fn debug_track_borrow(&self) { - #[cfg(debug_assertions)] - self.previous_borrow - .borrow_mut() - .insert(PreviousBorrow::borrowed()); - } - - #[cfg_attr(debug_assertions, track_caller)] - #[cfg_attr(debug_assertions, inline(never))] - #[allow(unused_must_use)] - pub(super) fn debug_track_borrow_mut(&self) { - #[cfg(debug_assertions)] - self.previous_borrow - .borrow_mut() - .insert(PreviousBorrow::borrowed_mut()); - } - } - impl PreviousBorrow { - #[track_caller] - #[inline(never)] - pub fn borrowed() -> Self { - Self { - location: *Location::caller(), - kind: BorrowKind::Immutable, - } - } - - #[track_caller] - #[inline(never)] - pub fn borrowed_mut() -> Self { - Self { - location: *Location::caller(), - kind: BorrowKind::Mutable, - } - } - } -} - pub mod error { + fn locations_display(locations: &[&'static std::panic::Location<'static>]) -> String { + locations + .iter() + .map(|location| format!(" - {location}")) + .collect::>() + .join("\n") + } #[derive(thiserror::Error, Debug)] pub enum UseSharedStateError { #[cfg_attr( debug_assertions, error( - "[{location}] {type_name} is already borrowed at [{previous_borrow}], so it cannot be borrowed mutably.", - previous_borrow = super::diagnostics::PreviousBorrow::display_opt(.previous_borrow) + "[{0}] {1} is already borrowed at, so it cannot be borrowed mutably. Previous borrows:\n[{2}]\n\n", + .source.attempted_at, + .type_name, + locations_display(&.source.already_borrowed_at) ) )] #[cfg_attr( not(debug_assertions), - error("{type_name} is already borrowed, so it cannot be borrowed mutably.") + error("{type_name} is already borrowed, so it cannot be borrowed mutably. (More detail available in debug mode)") )] AlreadyBorrowed { - source: core::cell::BorrowMutError, + source: super::BorrowMutError, type_name: &'static str, - /// Only available in debug mode - location: super::Location, - #[cfg(debug_assertions)] - previous_borrow: Option, }, #[cfg_attr( debug_assertions, error( - "[{location}] {type_name} is already borrowed mutably at [{previous_borrow}], so it cannot be borrowed anymore.", - previous_borrow = super::diagnostics::PreviousBorrow::display_opt(.previous_borrow) + "[{0}] {1} is already borrowed mutably at [{2}], so it cannot be borrowed anymore.", + .source.attempted_at, + .type_name, + locations_display(&.source.already_borrowed_at) ) )] #[cfg_attr( not(debug_assertions), - error("{type_name} is already borrowed mutably, so it cannot be borrowed anymore.") + error("{type_name} is already borrowed mutably, so it cannot be borrowed anymore. (More detail available in debug mode)") )] AlreadyBorrowedMutably { - source: core::cell::BorrowError, + source: super::BorrowError, type_name: &'static str, - /// Only available in debug mode - location: super::Location, - #[cfg(debug_assertions)] - previous_borrow: Option, }, } @@ -259,17 +187,11 @@ impl Drop for UseSharedStateOwner { /// State that is shared between components through the context system pub struct UseSharedState { pub(crate) inner: Rc>>, - #[cfg(debug_assertions)] - previous_borrow: Rc>>, } impl UseSharedState { fn new(inner: Rc>>) -> Self { - Self { - inner, - #[cfg(debug_assertions)] - previous_borrow: Default::default(), - } + Self { inner } } /// Notify all consumers of the state that it has changed. (This is called automatically when you call "write") @@ -282,16 +204,10 @@ impl UseSharedState { #[cfg_attr(debug_assertions, inline(never))] pub fn try_read(&self) -> UseSharedStateResult> { match self.inner.try_borrow() { - Ok(value) => { - self.debug_track_borrow(); - Ok(Ref::map(value, |inner| &inner.value)) - } + Ok(value) => Ok(Ref::map(value, |inner| &inner.value)), Err(source) => Err(UseSharedStateError::AlreadyBorrowedMutably { source, type_name: std::any::type_name::(), - location: debug_location!(), - #[cfg(debug_assertions)] - previous_borrow: *self.previous_borrow.borrow(), }), } } @@ -315,16 +231,12 @@ impl UseSharedState { pub fn try_write(&self) -> UseSharedStateResult> { match self.inner.try_borrow_mut() { Ok(mut value) => { - self.debug_track_borrow_mut(); value.notify_consumers(); Ok(RefMut::map(value, |inner| &mut inner.value)) } Err(source) => Err(UseSharedStateError::AlreadyBorrowed { source, type_name: std::any::type_name::(), - location: crate::debug_location!(), - #[cfg(debug_assertions)] - previous_borrow: *self.previous_borrow.borrow(), }), } } @@ -350,16 +262,10 @@ impl UseSharedState { #[cfg_attr(debug_assertions, inline(never))] pub fn try_write_silent(&self) -> UseSharedStateResult> { match self.inner.try_borrow_mut() { - Ok(value) => { - self.debug_track_borrow_mut(); - Ok(RefMut::map(value, |inner| &mut inner.value)) - } + Ok(value) => Ok(RefMut::map(value, |inner| &mut inner.value)), Err(source) => Err(UseSharedStateError::AlreadyBorrowed { source, type_name: std::any::type_name::(), - location: crate::debug_location!(), - #[cfg(debug_assertions)] - previous_borrow: *self.previous_borrow.borrow(), }), } } @@ -382,8 +288,6 @@ impl Clone for UseSharedState { fn clone(&self) -> Self { Self { inner: self.inner.clone(), - #[cfg(debug_assertions)] - previous_borrow: self.previous_borrow.clone(), } } }