Repository navigation
Tracking issue for std::ptr::eq, Arc::ptr_eq, and Rc::ptr_eq #36497
Description
Activity
- addedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]B-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.
on Sep 15, 2016 I needed Rc::ptr_eq to avoid a double borrow in a recursive data structure with Rc<RefCell< T >>. Thanks a lot!
@vadixidav It can be implemented outside of
stdby tweaking it a bit. Copy-pasting this into your code can unblock you untilRc::prt_eqis stabilized:pub fn rc_ptr_eq<T: ?Sized>(this: &Rc<T>, other: &Rc<T>) -> bool { let this_ptr: *const T = &*this; let other_ptr: *const T = &*other; this_ptr == other_ptr }
Reacted by Antoine Büsch, Ruud van Asseldonk and Robert GrosseSeem like good/easy APIs to stabilize!
@rfcbot fcp merge
Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams:
No concerns currently listed.
Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
federicomenaquintero commented
on Feb 17, 2017 ContributorMore actionsFWIW, I just found a good use for this in librsvg's port to Rust.
Librsvg has a Node structure for the tree of SVG objects. The C code keeps around
RsvgNode*values all over the place, including multiple references to the same value.Sometimes there is code like
if (current_node == tree_root)for special-casing... and you see where this is going.The things I expose to the C code are pointers that come from
Box<Rc<Node>>I also exposenode_ref()andnode_unref()functions so that C can get new references to existing nodes and discard them as needed.This means that
RsvgNode *node1 = rsvg_rust_cnode_new (...); /* returns a Box::into_raw (Box::new (Rc::new (Node))) */ RsvgNode *node2 = rsvg_node_ref (node1); assert (node1 == node2);is invalid now. What I want is to
assert (rsvg_node_is_same (node1, node2));and that can be implemented as
pub type RsvgNode = Rc<Node>; #[no_mangle] pub extern fn rsvg_node_is_same (raw_node1: *const RsvgNode, raw_node2: *const RsvgNode) -> bool { if raw_node1.is_null () && raw_node2.is_null () { true } else if !raw_node1.is_null () && !raw_node2.is_null () { let node1: &RsvgNode = unsafe { & *raw_node1 }; let node2: &RsvgNode = unsafe { & *raw_node2 }; Rc::ptr_eq (node1, node2) } else { false } }For now I'm using @SimonSapin's code (it's missing double asterisks in
&**thisand&**other), but it would indeed be nice to have an Rc::ptr_eq() in stable!For now I'm using @SimonSapin's code
I sometimes find convenient to make it less generic (when it’s only used with one
Ttype):fn same_node(a: *const Node, b: *const Node) -> bool { a == b }
This looks the same as
==, but since it expects raw pointer they can be coerced implicitly from references. (And, by the way,(*const T)::as_ref()can be more convenient thanis_null)#[no_mangle] pub extern fn rsvg_node_is_same (raw_node1: *const RsvgNode, raw_node2: *const RsvgNode) -> bool { match (raw_node1.as_ref(), raw_node2.as_ref()) { (Some(node1), Some(node2)) => same_node(&**node1, &**node2), (None, None) => true, _ => false } }
(Of course,
Rc::eqis nicer still.)ping @BurntSushi (checkbox)
🔔 This is now entering its final comment period, as per the review above. 🔔
- addedfinal-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.In the final comment period and will be merged soon unless new substantive objections are raised.
on Feb 28, 2017 The final comment period is now complete.
- added a commit that references this issue
on Mar 17, 2017 For future GitHub travelers, investigating
clippy::vtable_address_comparisons:Looks like the methods were stabilized with the
?Sizedbound, while the current impl doesn't quite handle them. Specifically,ptr_eqcan spuriously returnfalsefor identical trait objects. This is being tracked in #69757.This is not unique to these
ptr_eqmethods. Wide pointers to trait objects have been comparable with the==operator forever, with the same spurious results.
Implemented in #35992 as
#[unstable(feature = "ptr_eq")].std::ptr::eqis rust-lang/rfcs#1155.