Rc<RefCell<>> help

I am a bit stumped. I am working on a gtk-rs app. I have a state object which gets passed around as an Rc<RefCell < State> >. (State is a struct with some pub fields) I have a number of nested functions which take state, and which I call successfully like so:

let s = state.clone();
foo(s); // where foo is defined as fn foo(state: Rc<RefCell < State > >)

and within the function, i access state fields like so:

let config = state.borrow().config.clone();

This has been working fine until today, when I hit something strange…
From within one of the functions, when I try and borrow state, I get the following error:

let config = state.borrow().config.clone();
| ^^^^^^^^^^^^^^^^^^^^^ cannot infer type for Borrowed

error[E0609]: no field config on type &_

I don’t know what is going on here? Why is the type not infer-able in this function but it is in others? I don’t see any difference between uses… I am stuck…

Is it trying to call the Borrow::borrow trait method rather than the RefCell::borrow inherent method?

eg. Does changing that line of code to let config = RefCell::borrow(&state).config.clone(); make it work?

Wow. Yes that works. Thanks!

Another solution could be based on the fact that Rc implements AsRef:

let config = state.as_ref().borrow().config.clone();

It is a bit longer than using RefCell::borrow, but on the other hand it is a bit more functional (as in functional programming). However, it is just a matter of style.

Got this error too.
Rust 1.52.00 with IDEA.
And I finally figured out what is going on.
While my code has one use line
use std::borrow::{Borrow},
and
<Rc<RefCell>>.borrow()
will fail.
Just remove the use line and it work.
I guess the std::borrow may influece the borrow() calling,kind of some function has the same name or something.
Anyway that's not supposed to be developer problem.

Yeah, the Borrow trait (from ::std::borrow::Borrow) imbues Rc with a .borrow() method, that has priority and thus shadows the .borrow() of the inner RefCell. That is, to technically correctly call the inner .borrow() of the RefCell, one ought to write:

//   deref from `Rc<RefCell…>` to `&RefCell`:
//   vv
    (&*state).borrow()

It just happens that when the Borrow trait is not in scope, the lack of .borrow() on Rc triggers the "deref" sugar: it is a fallback behavior (albeit a behavior most people rely on, sometimes without even knowing it). So, when the trait is in scope, the fallback may no longer happen.

Imho, it's mainly a problem with RefCell::borrow having been named the same as <Rc<_> as Borrow>::borrow; it could have been name .read() and .write() like the RwLock counterpart does :woman_shrugging:

1 Like

This topic was automatically closed 30 days after the last reply. We invite you to open a new topic if you have further questions or comments.