don't use `RefCell<T>`

  • usually if you have to resort to RefCell<T>, it means something is wrong with your architecture

    2023-10-10
    • Cell<T> less so but still you should avoid it whenever possible

      2023-10-10
    • Rc<RefCell<T>> is an immediate red flag when I read someone’s code. it means they don’t really know what they’re doing and are just trying to sidestep the language

      2023-10-10
  • it’s really not that hard to avoid, try bumping your resources up a scope and borrow them from there

    2023-10-10
  • using RefCell has a few disadvantages

    2023-10-10
    • first, RefCell is literally turning off the borrow checker

      2023-10-10
      • or really deferring it until runtime, but then what’s the point. Rust’s borrowing rules are meant to prevent bugs, not cause more of them

        2023-10-10
    • second, your program can now panic in unexpected places, because it turns out runtime borrows can be really hard to predict

      2023-10-10
      • as evidenced by a random crash I once got while using druid which was caused by a overlapping mutable then immutable borrows at runtime

        2023-10-10
        • therefore maybe uhhh… don’t use it in libraries? :pleading:

          2023-10-10
    • third, it incurs a runtime overhead for the borrow checking, which in 99% of cases is totally unnecessary

      2023-10-10
      • (this is more about non-pessimization rather than premature microoptimization, so don’t yell at me with your “it’ll be fast enough” arguments please)

        2023-10-10
    • fourth, and this one is extremely easy to spot - your code becomes really verbose!

      2023-10-10
      • yes please, .borrow() me everywhere!

        2023-10-10
      • and you end up with lots of temporaries because of the Ref<'b, T> guards you have to keep in scope.

        2023-10-10
        • remember that you cannot do &ref_cell.borrow().some_field because that would drop the temporary Ref<'b, T> guard after the expression ends

          2023-10-10