Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Change UserState to outside of GraphEditorState #58

Merged
merged 7 commits into from
Sep 17, 2022

Conversation

kkngsm
Copy link
Contributor

@kkngsm kkngsm commented Aug 26, 2022

Changes

  1. Change UserState to outside of GraphEditorState #57
  2. add persistence feature flag

@kkngsm kkngsm changed the title Change UserState to outside of GraphEditorState Change UserState to outside of GraphEditorState #57 Aug 26, 2022
@kkngsm kkngsm changed the title Change UserState to outside of GraphEditorState #57 Change UserState to outside of GraphEditorState Aug 26, 2022
Copy link
Owner

@setzer22 setzer22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! 😄 Everything looks good, sorry it took me a while to review this.

I left a couple of questions just to make sure I understand the changes, but I don't think there's any actionable stuff.

@@ -29,13 +30,13 @@ pub struct GraphEditorState<NodeData, DataType, ValueType, NodeTemplate, UserSta
pub node_finder: Option<NodeFinder<NodeTemplate>>,
/// The panning of the graph viewport.
pub pan_zoom: PanZoom,
pub user_state: UserState,
pub _user_state: PhantomData<fn() -> UserState>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert with the rules about variance. Usually I've seen fn() -> T used as the PhantomData argument when you want to force the two types to be invariant. Why is invariance important here?

Copy link
Contributor Author

@kkngsm kkngsm Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your review!
The conclusion is that the impact of T can be reduced.

First, to correct you, according to The Rustonomicon fn() -> T is covariant.

Second, I quote from rust-lang/rust#46749 (comment)

PhantomData does 3 things:

  • variance
  • owns
  • auto trait opt outs

The key here is "owns" and "auto trait opt outs".

An example of "auto trait opt outs", For example, with a code like this:

use std::{marker::PhantomData, rc::Rc, thread};
#[derive(Debug, Default)]
struct Wrapper<T>{
    _phantom: PhantomData<T> 
}
fn main() {
    let out = Wrapper::<Rc<usize>>::default();
    thread::spawn(move|| out);
}

Run in Rust Playground
This code can't be compiled, because Rc<usize> and Outer<Rc<usize>> are not impled Send.
PhantomData<T> inherits !Send.

How to fix this:

use std::{marker::PhantomData, rc::Rc, thread};

#[derive(Debug, Default)]
struct Wrapper<T>{
    _phantom: PhantomData<fn()->T>
}
fn main() {
    let out = Wrapper::<Rc<usize>>::default();
    thread::spawn(move|| out);
}

Run in Rust Playgound
This doesn't inherit !Send and can be compiled.
Even if T is !Send, the Wrapper is Send.

Also, regarding "owns", I am not familiar with it, but I heard that PhantomData<fn()->T> is better than PhantomData<T> due to DropChekcer (unless you are implementing an unsafe Drop).

Comment on lines 365 to 376
/// If the persistence feature is enabled, Called once before the first frame.
/// Load previous app state (if any).
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
let state = if let Some(storage) = cc.storage {
eframe::get_value(storage, PERSISTENCE_KEY)
.unwrap_or_else(|| GraphEditorState::new(0.0))
} else {
GraphEditorState::new(0.0)
};
Self {
state,
user_state: MyGraphState::default(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice touch! I like that the example app keeps the state now. One question though: Are we sure this won't panic when the type definitions change? I'm assuming the unwrap_or_else call would catch this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the field name is different, get_value returns None, but since it is stored in Ron format, the difference between usize and i32, etc., seems to be cast.

@setzer22
Copy link
Owner

If you want to include the change discussed in #57 about passing &mut UserState please go ahead 👍

@kkngsm
Copy link
Contributor Author

kkngsm commented Sep 16, 2022

I changed the UserState args to mutable and made NodeGraphExample::new() simpler using syntax sugar.

@setzer22
Copy link
Owner

Looks ready to merge! Thanks again for the PR 😄

@setzer22 setzer22 merged commit 75308d0 into setzer22:main Sep 17, 2022
@kkngsm kkngsm deleted the outside-userstate branch September 17, 2022 20:53
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants