Code that leetcode can complie but my computer cannot

In leetcode 1302 th problem, it is a code that leetcode can compile but my computer cannot, as follows:

use std::rc::Rc;
use std::cell::RefCell;
use std::collections::VecDeque;

impl Solution {
    pub fn deepest_leaves_sum(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
        let mut res: i32 = 0;
        let mut queue: VecDeque<Rc<RefCell<TreeNode>>> = VecDeque::new();
        if let Some(node) = root {
            queue.push_front(node);
        }
        while !queue.is_empty()  {
            res = 0;
            for i in 0..queue.len() {
                if let Some(n) = queue.pop_back() {
                    let mut node = n.borrow_mut();
                    res += node.val;
                    if node.right.is_some() {
                        queue.push_front(node.right.take().unwrap());
                    }
                    if node.left.is_some() {
                        queue.push_front(node.left.take().unwrap());
                    }
                }
            }
        }
        res
    }
}

errors as follows:

error[E0609]: no field `val` on type `&mut std::rc::Rc<std::cell::RefCell<tree::TreeNode>>`
  --> src/p1301_t1400/p1302.rs:70:33
   |
70 |                     res += node.val;
   |                                 ^^^ unknown field

error[E0609]: no field `right` on type `&mut std::rc::Rc<std::cell::RefCell<tree::TreeNode>>`
  --> src/p1301_t1400/p1302.rs:71:29
   |
71 |                     if node.right.is_some() {
   |                             ^^^^^ unknown field

error[E0609]: no field `right` on type `&mut std::rc::Rc<std::cell::RefCell<tree::TreeNode>>`
  --> src/p1301_t1400/p1302.rs:72:47
   |
72 |                         queue.push_front(node.right.take().unwrap());
   |                                               ^^^^^ unknown field

error[E0609]: no field `left` on type `&mut std::rc::Rc<std::cell::RefCell<tree::TreeNode>>`
  --> src/p1301_t1400/p1302.rs:74:29
   |
74 |                     if node.left.is_some() {
   |                             ^^^^ unknown field

error[E0609]: no field `left` on type `&mut std::rc::Rc<std::cell::RefCell<tree::TreeNode>>`
  --> src/p1301_t1400/p1302.rs:75:47
   |
75 |                         queue.push_front(node.left.take().unwrap());
   |                                               ^^^^ unknown field

This code contains errors. It should not be able to compile.

But leetcode can compile, and this is leetcode's sample submission

Are you sure it compiles? It should not.

Doesn’t produce any compilation error for me, see this playground:

Maybe you had some kind of typo in the let mut node = n.borrow_mut(); line when trying it on your computer?

please see that Loading...

It requires registration. Make sure the code is the same, and leetcode is actually compiling and running it.

I just paste

5th floor can compile, please see Rust Playground

The code in the first post cannot be compiled as-is, since it doesn't contain definitions for Solution and TreeNode. It's possible, however, that these definitions are injected by LeetCode before compiling, therefore the combined code becomes valid.

upd: Just checked, that's indeed the case - if we define Solution explicitly, compiler tells us about conflicting definitions.

1 Like

However my local code also include TreeNode definition and Solution definition. And in local cannot compile.

Could you share your local code, then, and not the LeetCode one?

3 Likes

I got a new hypothesis: your local code might contain

use std::borrow::BorrowMut;

somewhere.

Rust Playground


You don’t typically need to import that trait; consider using use std::borrow; instead and writing trait bounds with BorrowMut as borrow::BorrowMut. Calling the borrow_mut method from that trait should still work in generic functions with borrow::BorrowMut trait bounds, and on concrete types – outside of such functions – you typically don’t need that method at all.

Alternatively, if you want to keep the import as-is, you’d need to modify the line that defines node to let mut node = (*n).borrow_mut(); or to let mut node = RefCell::borrow_mut(&n);.


Edit: To explan the problem: It’s due to how method resolution works in Rust. You call borrow_mut on a Rc<RefCell<TreeNode>>. Rc<T> dereferences to T. So method resolution considers the following types in this order as self-type for the method

  1. Rc<RefCell<TreeNode>>
  2. &Rc<RefCell<TreeNode>>
  3. &mut Rc<RefCell<TreeNode>>
  4. RefCell<TreeNode>
  5. &RefCell<TreeNode>
  6. &mut RefCell<TreeNode>

The RefCell::borrow_mut you want is a method on &RefCell<TreeNode>. The blanket implementation BorrowMut<T> for T gives rise to a <Rc<RefCell<TreeNode>> as BorrowMut<Rc<RefCell<TreeNode>>>>::borrow_mut method which is a method on &mut Rc<RefCell<TreeNode>> which comes earlier in the list above, so it takes precedence. This method is implemented by just returning the mutable reference unmodified, so with the BorrowMut trait in scope, the line let mut node = n.borrow_mut(); becomes equivalent to let mut node = &mut n;, hence the error messages talking about the type &mut Rc<RefCell<TreeNode>>.

If BorrowMut isn’t imported, it’s methods don’t apply for method resolutions (except for values of generic type T in generic functions when there was an explicit T: std::borrow::BorrowMut bound).

The two solutions keeping the use std::borrow::BorrowMut I posed were

  • using (*n) to do the dererefencing manually, so method resoluation only starts looking at number 4. in the list above (skipping the first three); there’s also a BorrowMut implementation for RefCell<TreeNode> directly, but that’s on &mut RefCell<TreeNode> and comes later than &RefCell<TreeNode>
  • manually naming the RefCell::borrow_mut method. You can pass it (&n) even though that’s &Rc<RefCell<TreeNode>>, because that type can deref-coerce into &RefCell<TreeNode>. Since we name the function explicitly, the desired argument type is known and the coercion can be introduced by the compiler
4 Likes

Thank you. I got it.

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