Skip to content

Instantly share code, notes, and snippets.

@gftea
Created August 28, 2022 22:15
Show Gist options
  • Save gftea/8df5d6cd96fdc6d06d4bc75f116cc00a to your computer and use it in GitHub Desktop.
Save gftea/8df5d6cd96fdc6d06d4bc75f116cc00a to your computer and use it in GitHub Desktop.
#![allow(unused)]
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug, PartialEq)]
struct Node;
fn main() {
{
// case 1, normal
let x = Rc::new(RefCell::new(Node));
// `x.borrow()` is derived by compiler as below
// 1. Rc<RefCell<Node>> automatically dereferences to RefCell<Node>
// 2. then RefCell::borrow() is called
assert_eq!(*x.borrow(), Node);
}
{
// case 2, trait pollution
// compiler cannot automatically dereferences due to ambiguity.
// because: `borrow` method can be from two traits implementations.
// - import `std::rc::Rc` add `impl<T> Borrow<T> for Rc<T>`
// - import `std::borrow::Borrow` add blanket implementation `impl<T> Borrow<T> for T`
use std::borrow::Borrow;
let x = Rc::new(RefCell::new(Node));
{// error case
// assert_eq!(*x.borrow(), Node) // uncomment this line to see compiler error
}
{// solution 1
use std::ops::Deref; // bring `Deref` to scope and use explicitly
assert_eq!(*x.deref().borrow(), Node);
}
{// solution 2 use full qualitfied type
// 1st borrow return RefCell<Node>, 2nd borrow return Ref<_,Node>
// <Rc<RefCell<Node>> as Borrow<RefCell<Node>>>::borrow(&x) is equivalent to x.deref()
// but x.deref() is much more concise.
assert_eq!(*<Rc<RefCell<Node>> as Borrow<RefCell<Node>>>::borrow(&x).borrow(), Node);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment