Conversation
Today in This Should Be Easy But in #Rust It Apparently Isn't: how do I encapsulate the widget initialization (without triggering E0515) in this example, so it becomes reusable?

https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f31dd1ecf5530b11e301bb19af85b0fa
2
1
0

@buherator I’m not really sure what you mean by incapsulate the initialisation. Maybe showing the code you are getting an error from would help.

1
0
0
@alphastrata Thanks! I'll probably end a up a solution like that but still wonder if this can be achieved without Box/refcounts (should've added to the question)?
0
0
0
@edmcbane Imagine that initialization is more complex and I want to provide a library that hides that complexity, exposing something like setup_widget() and deinit_all().

You can see an E0515 here (among other things), but I intentionally refrained from providing my attempts because I suspect there is a completely different Rust pattern for similar cases:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=0f4a1eeba2c33741fafc059d717e87bb

It's important that I can't touch Session or Widget as they are provided by a library (with FFI).
0
0
0

@buherator@infosec.place Can you be more specific about what you want to do?

1
0
0
@addison From a different branch of this convo:

"Imagine that initialization is more complex and I want to provide a library that hides that complexity, exposing something like setup_widget() and deinit_all()."

https://infosec.place/notice/B3RIRrdtPQog3eUc2y
1
0
0

@buherator@infosec.place Yeah, you'll need some indirection here. You can't move session while it is borrowed. Alternatively, you can keep the widgets in the session (e.g., in a vec or smth) and only offer (mutably) borrowed access to the widgets by an ID or something. It just depends on what's appropriate for your use case; presumably, widgets should always be deinitialized when the session is, so the session should "own" the widgets.

1
0
0
@addison Thanks, that makes sense, but I can't touch Session as it comes from a dependency. There is definitely a lifetime issue here too (esp. because the actual tree of objects goes ~5 levels deep).

I think the root of my Q is if there is a way to create a "will" for Rust functions/scopes that would say "after my death my caller will inherit all that I own (so please don't free shit up)"?
1
0
0

@buherator@infosec.place Then it's time for an Rc<RefCell<Session>> instead of a lifetime (or Arc<RwLock<...>> if asynchronous). Just be careful to avoid cycles. :)

2
0
0

@buherator@infosec.place For deinit_all you definitely need some wrapper object keeping track of the widgets, but that should be compatible here. If the session can die independently, use Weak instead of Rc/Arc.

0
0
1
@addison Thanks, that's in line with @alphastrata's suggestion and the advice I got afk.

I'm quite new to Rust and it's strange that something as simple as moving a couple of lines of code into a function (I'm still considering a macro actually) can require this much consideration, but I guess this is the price we pay for stability.
1
0
0

@buherator@infosec.place Yeah, Rust will really force you to be careful here. In other languages, you might initialize the widget with a pointer, but then if you move the value, the pointer is invalid. Similarly with concurrent access to the session object. You're prohibited from constructions which are potentially faulty.

0
0
1
@alphastrata The root of the issue is that the library I'm using is not originally in/for Rust, so such best practices simply don't exist in their world...
0
0
0