Skip to content

Tracking issue for std::ptr::eq, Arc::ptr_eq, and Rc::ptr_eq #36497

@SimonSapin

Description

@SimonSapin
Contributor

Implemented in #35992 as #[unstable(feature = "ptr_eq")].

std::ptr::eq is rust-lang/rfcs#1155.

Activity

added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
B-unstableBlocker: Implemented in the nightly compiler and unstable.
on Sep 15, 2016
vadixidav

vadixidav commented on Nov 25, 2016

@vadixidav
Contributor

I needed Rc::ptr_eq to avoid a double borrow in a recursive data structure with Rc<RefCell< T >>. Thanks a lot!

SimonSapin

SimonSapin commented on Nov 25, 2016

@SimonSapin
ContributorAuthor

@vadixidav It can be implemented outside of std by tweaking it a bit. Copy-pasting this into your code can unblock you until Rc::prt_eq is 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
}
alexcrichton

alexcrichton commented on Feb 14, 2017

@alexcrichton
Member

Seem like good/easy APIs to stabilize!

@rfcbot fcp merge

rfcbot

rfcbot commented on Feb 14, 2017

@rfcbot

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

federicomenaquintero commented on Feb 17, 2017

@federicomenaquintero
Contributor

FWIW, 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 expose node_ref() and node_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 &**this and &**other), but it would indeed be nice to have an Rc::ptr_eq() in stable!

SimonSapin

SimonSapin commented on Feb 17, 2017

@SimonSapin
ContributorAuthor

For now I'm using @SimonSapin's code

I sometimes find convenient to make it less generic (when it’s only used with one T type):

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 than is_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::eq is nicer still.)

alexcrichton

alexcrichton commented on Feb 28, 2017

@alexcrichton
Member

ping @BurntSushi (checkbox)

rfcbot

rfcbot commented on Feb 28, 2017

@rfcbot

🔔 This is now entering its final comment period, as per the review above. 🔔

added
final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
on Feb 28, 2017
rfcbot

rfcbot commented on Mar 10, 2017

@rfcbot

The final comment period is now complete.

added a commit that references this issue on Mar 17, 2017
698c1bb
matklad

matklad commented on Dec 31, 2020

@matklad
Contributor

For future GitHub travelers, investigating clippy::vtable_address_comparisons:

Looks like the methods were stabilized with the ?Sized bound, while the current impl doesn't quite handle them. Specifically, ptr_eq can spuriously return false for identical trait objects. This is being tracked in #69757.

SimonSapin

SimonSapin commented on Dec 31, 2020

@SimonSapin
ContributorAuthor

This is not unique to these ptr_eq methods. Wide pointers to trait objects have been comparable with the == operator forever, with the same spurious results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    B-unstableBlocker: Implemented in the nightly compiler and unstable.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @federicomenaquintero@alexcrichton@SimonSapin@aturon@matklad

        Issue actions

          Tracking issue for std::ptr::eq, Arc::ptr_eq, and Rc::ptr_eq · Issue #36497 · rust-lang/rust